Fix PHP Fatal error: Uncaught DivisionByZeroError: Division by zero

beginner🐘 PHP2026-06-19| PHP 8.0+ (Linux, macOS, Windows). PHP 7.x chỉ tạo ra Warning thay vì throw Error.

Error Message

Fatal error: Uncaught DivisionByZeroError: Division by zero in /path/to/script.php
#php#math#error#runtime

Lỗi Gặp Phải

Fatal error: Uncaught DivisionByZeroError: Division by zero in /path/to/script.php on line 12

PHP 8 đã thay đổi cách xử lý phép chia cho số không. Trong PHP 7, chia cho số không chỉ tạo ra một Warning và chương trình vẫn tiếp tục — trả về false rồi chạy tiếp. PHP 8 biến nó thành một DivisionByZeroError được ném ra, và script dừng lại ngay lập tức. Nếu bạn vừa nâng cấp PHP gần đây, đó rất có thể là lý do tại sao thứ gì đó "chạy được" trước đây giờ lại đang crash trên môi trường production.

Nguyên Nhân Gốc Rễ

  • Chia cho một biến đang chứa giá trị 0, null, hoặc chuỗi rỗng (chuỗi rỗng sẽ được ép kiểu thành 0)
  • Toán tử modulo % với số chia bằng không — cùng lỗi, khác toán tử
  • Số chia động đến từ input người dùng, truy vấn cơ sở dữ liệu, hoặc file config mà chưa được kiểm tra trước khi đưa vào phép tính

Cách Sửa Từng Bước

1. Kiểm tra số chia trước khi thực hiện phép chia

Chín trong mười trường hợp, một kiểm tra đơn giản trước khi chia là đủ. Hãy xác nhận số chia không phải là số không trước khi thực hiện phép tính.

<?php
// Bị crash khi $count là 0 — ví dụ: chưa có đơn hàng nào trong báo cáo doanh số
$average = $total / $count;

// Phiên bản an toàn
if ($count === 0) {
    $average = 0; // hoặc null, hoặc ném một exception riêng cho nghiệp vụ
} else {
    $average = $total / $count;
}

2. Dùng toán tử ternary cho cú pháp gọn hơn

Khi khối if/else cảm thấy rườm rà, một toán tử ternary hoạt động tốt không kém:

<?php
$average   = $count !== 0 ? $total / $count : 0;
$remainder = $count !== 0 ? $total % $count : 0;

3. Dùng fdiv() cho phép chia số thực (PHP 8+)

fdiv() tuân theo chuẩn IEEE 754: chia cho số không và bạn nhận được INF, -INF, hoặc NAN — không bao giờ ném exception. Hàm này rất tiện trong các pipeline tính toán số khi bạn muốn xử lý kết quả bất thường sau đó thay vì phải kiểm tra từng số chia một.

<?php
$result = fdiv($total, $count); // trả về INF nếu $count === 0, không bao giờ ném exception

if (!is_finite($result)) {
    $result = 0;
}

4. Bắt DivisionByZeroError trong các pipeline tính toán

Đôi khi bạn không thể dễ dàng kiểm tra số chia trước — chẳng hạn trong một chuỗi các giá trị được tính toán liên tiếp. Dùng try/catch giúp phần còn lại của ứng dụng vẫn chạy được dù một phép tính nào đó thất bại.

<?php
try {
    $rate = $processed / $total;
} catch (\DivisionByZeroError $e) {
    error_log('Division by zero: ' . $e->getMessage());
    $rate = 0;
}

5. Kiểm tra dữ liệu đầu vào động ngay tại điểm nhận

Giá trị do người dùng gửi lên, dữ liệu POST từ form, và các cột trong cơ sở dữ liệu là nguồn phổ biến nhất tạo ra những số không bất ngờ. Hãy loại bỏ chúng trước khi chúng đến được phần logic tính toán của bạn.

<?php
$count = (int) $_POST['count'];
if ($count  'count must be greater than zero']);
    exit;
}

$average = $total / $count; // an toàn — $count là số dương

6. Modulo cho số không — cùng lỗi, cùng cách sửa

Toán tử % cũng ném DivisionByZeroError. Cùng cách kiểm tra, khác toán tử:

<?php
// Bị crash
$remainder = $value % $divisor;

// Modulo số nguyên an toàn
$remainder = $divisor !== 0 ? $value % $divisor : 0;

// Với số thực, dùng fmod() — trả về NAN khi số chia là 0, không bao giờ ném exception
$remainder = fmod($value, $divisor);

Kiểm Tra Kết Quả

Lưu đoạn code này thành file test_division.php và chạy để xác nhận bản sửa hoạt động đúng:

<?php
$total = 100;
$count = 0;

$average = $count !== 0 ? $total / $count : 0;
echo "Average: $average\n"; // Average: 0

$result = fdiv($total, $count);
echo "fdiv result: $result\n";                                    // fdiv result: INF
echo "is_finite: " . (is_finite($result) ? 'yes' : 'no') . "\n"; // no

Chạy lệnh: php test_division.php. Không có lỗi fatal nghĩa là bạn đã xong.

Sự Khác Biệt Giữa PHP 7 và PHP 8

Đang nâng cấp từ PHP 7? Hành vi đã thay đổi theo hai cách:

  • PHP 7: $x / 0 phát sinh Warning: Division by zero và trả về false; $x % 0 đã ném DivisionByZeroError rồi
  • PHP 8+: cả / lẫn % đều ném DivisionByZeroError

Code PHP 7 chỉ kiểm tra giá trị trả về là false sẽ bị lỗi trên PHP 8. Cách kiểm tra if ($divisor !== 0) hoạt động trên cả hai phiên bản — hãy dùng cách đó thay thế.

Mẹo Nhanh

  • Dùng so sánh chặt !== 0, không dùng so sánh lỏng != 0 — so sánh lỏng có thể hoạt động không như mong đợi với null và chuỗi rỗng
  • Ép kiểu rõ ràng các giá trị lấy từ cơ sở dữ liệu trước khi chia: (int) $row['count'] hoặc (float) $row['amount']
  • intdiv() cũng ném DivisionByZeroError khi số chia bằng không — cùng cách kiểm tra áp dụng cho hàm này
  • Đặt display_errors = Off trên môi trường production và ghi log ra file; stack trace không bao giờ nên lộ ra cho người dùng cuối

Related Error Notes