Sửa lỗi 'Passing null to parameter of type string' trong PHP 8.1+

beginner🐘 PHP2026-06-24| PHP 8.1, 8.2, hoặc 8.3 chạy trên Linux (Ubuntu/Debian), Nginx/Apache, hoặc Docker container.

Error Message

Deprecated: str_replace(): Passing null to parameter #1 ($search) of type array|string is deprecated in /var/www/html/app.php on line 42
#php81#loi-deprecated#xu-ly-null#di-tru-php#backend

Cách khắc phục nhanh

PHP 8.1 và các phiên bản mới hơn không còn chấp nhận giá trị null cho các hàm nội bộ (internal functions) yêu cầu kiểu string. Để giải quyết vấn đề này ngay lập tức, hãy sử dụng toán tử null coalescing (?? '') để đảm bảo luôn cung cấp một chuỗi trống mặc định.

// ❌ Mã nguồn cũ (Gây ra cảnh báo Deprecated)
$output = str_replace($search, $replace, $subject);

// ✅ Khuyên dùng: Null Coalescing
$output = str_replace($search ?? '', $replace ?? '', $subject ?? '');

// ✅ Giải pháp thay thế: Ép kiểu tường minh
$output = str_replace((string)$search, (string)$replace, (string)$subject);

Tại sao tệp nhật ký của bạn đột ngột tăng dung lượng

Việc nâng cấp lên PHP 8.1 thường đi kèm với một bất ngờ khó chịu: các tệp nhật ký lỗi (error logs) tăng thêm hàng trăm megabyte chỉ trong một ngày. Trước đây, PHP khá thoải mái. Nếu bạn truyền null vào các hàm như strlen hoặc trim, PHP sẽ âm thầm chuyển đổi nó thành một chuỗi trống. Điều này tuy tiện lợi nhưng lại che giấu các lỗi tiềm ẩn trong logic dữ liệu của bạn.

Đội ngũ phát triển PHP hiện đang thắt chặt tính an toàn về kiểu dữ liệu (type safety). Việc truyền null vào các tham số này đã chính thức bị loại bỏ (deprecated). Mặc dù mã nguồn của bạn hiện vẫn chạy được, nhưng PHP 9.0 có khả năng sẽ chuyển đổi các cảnh báo này thành ngoại lệ TypeError. Điều này sẽ khiến toàn bộ ứng dụng của bạn bị dừng hoạt động thay vì chỉ làm đầy tệp nhật ký.

Có thể bạn đang gặp phải mẫu lỗi cụ thể sau:

Deprecated: str_replace(): Passing null to parameter #1 ($search) of type array|string is deprecated in /var/www/html/app.php on line 42

Các tình huống thường gặp

1. Các cột cơ sở dữ liệu cho phép giá trị Null

Đây là nguyên nhân chính. Hãy tưởng tượng bạn truy xuất hồ sơ người dùng trong đó cột middle_name có thể để trống (nullable). Nếu người dùng không có tên đệm, trình điều khiển cơ sở dữ liệu của bạn sẽ trả về null. Việc truyền trực tiếp giá trị đó vào một hàm xử lý chuỗi giờ đây sẽ kích hoạt cảnh báo.

$user = $db->fetch("SELECT middle_name FROM users WHERE id = 123");
// Nếu cột là NULL, dòng này hiện sẽ gây ra cảnh báo:
echo strlen($user['middle_name']); 

2. Dữ liệu trả về từ API không thể dự đoán

Các API bên ngoài nổi tiếng với dữ liệu không nhất quán. Một trường JSON có thể là chuỗi trong phản hồi này nhưng lại là null trong phản hồi tiếp theo. Nếu mã nguồn của bạn mặc định trường đó luôn là chuỗi, tệp nhật ký môi trường thực tế (production logs) của bạn sẽ nhanh chóng bị lấp đầy bởi các thông báo deprecation trong các giai đoạn lưu lượng truy cập cao.

3. Các trường nhập liệu không bắt buộc trong Form

Các framework đôi khi chuẩn hóa các đầu vào form trống thành null. Nếu bạn xử lý một bộ lọc tìm kiếm hoặc một trường tiểu sử không bắt buộc mà không kiểm tra kiểu dữ liệu, bạn sẽ gặp ngay rào cản deprecation này.

Các phương pháp khắc phục thực tế

Phương pháp 1: Toán tử Null Coalescing

Sử dụng ?? '' là giải pháp sạch sẽ và dễ đọc nhất. Nó thông báo rõ ràng cho các lập trình viên khác: "Chúng tôi mong đợi một chuỗi, nhưng nếu thiếu dữ liệu, hãy coi đó là chuỗi trống."

// An toàn và ngắn gọn
$slug = strtolower($title ?? '');

Phương pháp 2: Ép kiểu chuỗi tường minh

Ép kiểu là một phương pháp "mạnh bạo" hoạt động tốt cho việc tái cấu trúc mã nguồn (refactoring) trên quy mô lớn. Nó đặc biệt hữu ích khi bạn thực hiện tìm kiếm và thay thế trên toàn bộ hàng nghìn dòng mã cũ (legacy code). Trong PHP, (string)null luôn có giá trị là "".

$description = trim((string)$data->description);

Phương pháp 3: Khắc phục ở cấp độ Model

Nếu bạn sử dụng một ORM như Eloquent của Laravel, hãy xử lý việc chuyển đổi ngay tại nguồn. Điều này ngăn chặn null tiếp cận vào logic nghiệp vụ của bạn. Sử dụng một Attribute để đảm bảo giá trị luôn là một chuỗi khi được truy cập.

// Ví dụ Laravel: Đảm bảo trả về một chuỗi
protected function biography(): Attribute
{
    return Attribute::make(
        get: fn (?string $value) => $value ?? '',
    );
}

Tìm các điểm nóng trong mã nguồn của bạn

Đừng đợi người dùng kích hoạt mọi luồng xử lý mã có thể. Bạn có thể chủ động tìm các vấn đề này bằng cách sử dụng grep để tìm kiếm các hàm xử lý chuỗi phổ biến trong thư mục nguồn của bạn:

grep -rnE "(str_replace|strlen|trim|explode|strpos)" ./src

Để có giải pháp mạnh mẽ hơn, hãy sử dụng PHPStan. Các công cụ phân tích tĩnh có thể xác định mọi trường hợp trong đó một biến có thể null được truyền vào một tham số hàm không cho phép null. Cách này an toàn hơn nhiều so với việc tìm kiếm thủ công.

# Cài đặt PHPStan
composer require --dev phpstan/phpstan

# Chạy phân tích ở cấp độ 5 hoặc cao hơn
vendor/bin/phpstan analyse src --level 5

Cách xác minh việc khắc phục

Sau khi bạn đã áp dụng các thay đổi, hãy xác nhận rằng các cảnh báo đã biến mất. Việc chỉ đơn thuần ẩn các lỗi trong cấu hình của bạn chỉ là một biện pháp tạm thời, không phải là cách khắc phục triệt để.

  • Bật báo cáo lỗi đầy đủ trong môi trường phát triển của bạn: error_reporting(E_ALL);
  • Chạy bộ kiểm thử tự động hoặc kích hoạt trang bị ảnh hưởng một cách thủ công.
  • Theo dõi tệp nhật ký lỗi của PHP-FPM hoặc Apache (ví dụ: tail -f /var/log/php-fpm.log).
  • Xác minh rằng không có mục "Deprecated" mới nào xuất hiện khi mã được thực thi.

Related Error Notes