TL;DR
PHP 7.2 đã siết chặt hàm count() — giờ đây nó sẽ ném cảnh báo khi bạn truyền vào null hoặc bất kỳ thứ gì không phải mảng hay Countable. Hãy kiểm tra null trước khi đếm:
// Trước đây (lỗi trên PHP 7.2+)
$total = count($items);
// Sau — phiên bản an toàn
$total = is_array($items) || $items instanceof Countable ? count($items) : 0;
// Hoặc cách viết ngắn gọn mà nhiều người hay dùng
$total = count($items ?? []);
Nguyên Nhân Gây Ra Cảnh Báo Này
Trong PHP 7.1 và trước đó, count(null) âm thầm trả về 0. count('hello') trả về 1. Không gây phiền toái, không có cảnh báo — điều đó cũng có nghĩa là các lỗi tiềm ẩn bị bỏ qua trong nhiều năm.
PHP 7.2 đã thay đổi quy tắc. Bây giờ count() chỉ chấp nhận mảng hoặc đối tượng có cài đặt Countable. Truyền vào null, số nguyên, chuỗi, hay boolean và bạn sẽ nhận được:
PHP Warning: count(): Parameter must be an array or an object that implements Countable in /var/www/html/index.php on line 42
Nguyên nhân điển hình: một truy vấn cơ sở dữ liệu trả về null khi không có kết quả, và code của bạn gọi count() trên đó mà không kiểm tra trước.
Bước 1 — Tìm Biến Gây Ra Lỗi
Cảnh báo cho bạn biết chính xác nơi cần xem — tên file và số dòng. Mở file đó, tìm lời gọi count(), và thêm var_dump() ngay phía trên:
var_dump($items); // $items thực sự chứa gì?
$total = count($items);
Thấy NULL trong kết quả? Đó là thủ phạm. Dưới đây là những chỗ null thường xuất hiện:
- Truy vấn PDO/MySQLi không có kết quả — một số driver trả về
nullthay vì[] - Một hàm đi vào nhánh return mà không có giá trị trả về tường minh (PHP trả về
nullngầm định) json_decode()thất bại do JSON sai định dạng — trả vềnullmà không báo lỗi- Biến chưa được khởi tạo
- Giá trị config hoặc session bị thiếu
Các Cách Sửa Lỗi
Cách 1 — Null coalescing (gọn nhất cho PHP 7.0+)
$total = count($items ?? []);
Khi $items là null, toán tử ?? sẽ thay thế bằng mảng rỗng. count([]) trả về 0. Xong. Cách này xử lý được 90% trường hợp thực tế và dễ đọc ngay khi nhìn vào.
Cách 2 — Kiểm tra kiểu dữ liệu tường minh
if (is_array($items) || $items instanceof Countable) {
$total = count($items);
} else {
$total = 0;
}
Dài dòng hơn, nhưng hữu ích khi bạn cần xử lý trường hợp không phải mảng theo cách khác — chẳng hạn ghi log cảnh báo hoặc ném exception thay vì mặc định về 0.
Cách 3 — Ép kiểu về mảng
$total = count((array) $items);
Hoạt động được, nhưng hãy chú ý các trường hợp đặc biệt: (array) null → [] (count 0), nhưng (array) 'hello' → ['hello'] (count 1). Chỉ dùng cách này khi bạn chắc chắn giá trị là mảng hoặc null — không có gì khác.
Cách 4 — Sửa từ hàm nguồn
Đôi khi cách sửa đúng không phải ở chỗ gọi count() — mà là ở phía trên. Hãy làm cho hàm trả về dữ liệu luôn trả về một mảng:
// Dễ lỗi: có thể trả về null nếu truy vấn thất bại
function getUsers(PDO $pdo): ?array {
$stmt = $pdo->query('SELECT * FROM users');
return $stmt->fetchAll();
}
// Chắc chắn: luôn trả về mảng, nơi gọi không cần đoán
function getUsers(PDO $pdo): array {
$stmt = $pdo->query('SELECT * FROM users');
return $stmt ? $stmt->fetchAll(PDO::FETCH_ASSOC) : [];
}
Sửa lỗi dành riêng cho WordPress / Plugin
Thấy lỗi này sau khi nâng cấp WordPress lên PHP 7.2+? Plugin chưa được cập nhật. Vá tạm thời như sau:
// Code plugin gốc (lỗi trên PHP 7.2+)
$count = count($some_option);
// Đã vá
$count = is_array($some_option) ? count($some_option) : 0;
Cách này giúp bạn có thêm thời gian, nhưng cách sửa thực sự là mở báo cáo lỗi với tác giả plugin và chuyển sang phiên bản được bảo trì.
Im Lặng Cảnh Báo vs. Sửa Thực Sự
Một số câu trả lời trên Stack Overflow gợi ý dùng @count($items) để bịt cảnh báo. Đừng làm vậy. Bịt lỗi có nghĩa là bạn sẽ không bao giờ biết khi nào $items là null mà đáng lẽ không được như vậy. Cảnh báo tồn tại có lý do — đó là PHP đang cho bạn biết có điều gì đó bất thường đang xảy ra. Hãy sửa nguyên nhân, không phải triệu chứng.
Xác Nhận Bản Sửa Lỗi
Áp dụng bản sửa, rồi theo dõi log để xác nhận cảnh báo đã biến mất:
# Theo dõi log lỗi PHP của bạn
tail -f /var/log/php/error.log
# Hoặc kiểm tra log lỗi web server
tail -f /var/log/nginx/error.log
# Tạm thời bật toàn bộ báo cáo lỗi để bắt các vấn đề khác
error_reporting(E_ALL);
ini_set('display_errors', '1');
Kích hoạt đường dẫn code đang lỗi. Không thấy cảnh báo trong log? Bạn đã xong.
Để kiểm tra nhanh trên terminal:
php -r "echo count(null);" # PHP 7.1: in 0 im lặng
# PHP 7.2+: Cảnh báo + in 0
php -r "echo count(null ?? []);" # PHP 7.2+: in 0, không có cảnh báo
Nếu Bạn Đang Dùng Codebase Cũ
Chuyển từ PHP 7.1 lên 7.2+ trên một ứng dụng lớn? Hãy chuẩn bị cho hàng chục cảnh báo kiểu này xuất hiện cùng lúc. Sửa ngay từng nơi gọi là không thực tế. Một hàm helper giúp bạn di chuyển hàng loạt:
/**
* Thay thế drop-in cho count() không cảnh báo khi gặp null.
*/
function safe_count($value): int {
if (is_array($value) || $value instanceof Countable) {
return count($value);
}
return 0;
}
Tìm kiếm toàn project với từ khóa count( và thay bằng safe_count( ở những chỗ phù hợp. Về lâu dài không đẹp, nhưng giúp bạn unblock quá trình nâng cấp PHP mà không mất cả tuần để đào bới từng nơi gọi.

