Cách khắc phục lỗi "Deprecated: Creation of dynamic property" trong PHP 8.2

intermediate🐘 PHP2026-05-30| PHP 8.2+, Linux (Ubuntu/Debian), macOS, Windows, Docker (php:8.2-fpm)

Error Message

Deprecated: Creation of dynamic property ClassName::$property is deprecated
#php#php82#loi-thoi#thuoc-tinh-dong#nang-cap

Cảnh báo Production lúc 2 giờ sángBạn vừa nâng cấp máy chủ lên PHP 8.2. Đột nhiên, các bản ghi lỗi (error logs) bùng nổ. Mặc dù ứng dụng vẫn đang chạy về mặt kỹ thuật, những cảnh báo lỗi thời này đang nhấn chìm các vấn đề thực sự. Nếu bạn đang xử lý hàng nghìn yêu cầu, các bản ghi này có thể dễ dàng phình to lên đến vài gigabyte chỉ trong một đêm. PHP 8.2 chính thức kết thúc kỷ nguyên "tự do" của các thuộc tính động để phát hiện các lỗi ngầm và tối ưu hóa hiệu suất engine.

Thông báo lỗiTìm kiếm cảnh báo cụ thể này trong log hoặc trên màn hình khi display_errors đang hoạt động:

Deprecated: Creation of dynamic property User::$email is deprecated in /var/www/html/src/Models/User.php on line 42

Tại sao điều này xảy raTrước PHP 8.2, bạn có thể gán giá trị cho các thuộc tính không tồn tại mà không gặp bất kỳ phàn nàn nào từ engine. Nó tiện lợi nhưng nguy hiểm. Một lỗi đánh máy đơn giản như $this->emial = $val; sẽ không gây ra lỗi; nó chỉ tạo ra một thuộc tính mới vô dụng. PHP hiện đã gắn cờ hành vi này. Đến PHP 9.0, sự "tiện lợi" này sẽ trở thành một lỗi Fatal Error làm sập trang web của bạn.

Cách khắc phục### 1. Khai báo thuộc tính một cách rõ ràng (Tiêu chuẩn vàng)Đây là giải pháp mạnh mẽ nhất. Việc khai báo thuộc tính giúp mã nguồn dễ đọc hơn, hỗ trợ tự động hoàn thành (autocomplete) trên IDE và cho phép các công cụ phân tích tĩnh phát hiện lỗi trước khi đưa lên production.

Mã lỗi:

class User {
    public function __construct($data) {
        $this->email = $data['email']; // Kích hoạt cảnh báo nếu chưa khai báo
    }
}

Mã đã sửa:

class User {
    public string $email; // Khai báo rõ ràng với một kiểu dữ liệu

    public function __construct($data) {
        $this->email = $data['email'];
    }
}

2. Sử dụng Attribute #[AllowDynamicProperties] (Lối tắt cho mã nguồn cũ)Khi làm việc với một kho mã nguồn cũ khổng lồ hoặc các đối tượng chuyển đổi dữ liệu (DTO), việc khai báo mọi thuộc tính có thể mất hàng tuần. Hãy sử dụng attribute này để thông báo cho engine rằng một class cụ thể được phép giữ tính chất "động".

use AllowDynamicProperties;

#[AllowDynamicProperties]
class LegacyModel {
    public function setDynamic($name, $value) {
        $this->$name = $value; // Không kích hoạt cảnh báo
    }
}

3. Sử dụng stdClass cho dữ liệu chungCác đối tượng chung được tạo qua stdClass được miễn trừ khỏi quy tắc này. Nếu bạn sử dụng một đối tượng chỉ đơn thuần như một thùng chứa dữ liệu tạm thời, stdClass vẫn là một lựa chọn an toàn và không gây cảnh báo.

$data = new stdClass();
$data->tempKey = 'Value'; // Hoàn toàn ổn trong PHP 8.2

4. Sử dụng Magic Methods (__set và __get)Việc xử lý gán giá trị thông qua __set() sẽ bỏ qua kiểm tra lỗi thời. Điều này cho PHP biết rằng bạn đang chủ động quản lý dữ liệu động thay vì mắc lỗi đánh máy.

class FlexibleConfig {
    private array $settings = [];

    public function __set($name, $value) {
        $this->settings[$name] = $value;
    }

    public function __get($name) {
        return $this->settings[$name] ?? null;
    }
}

$config = new FlexibleConfig();
$config->api_key = 'secret'; // Hoạt động mà không có cảnh báo

Xác minh bản sửa lỗiXác nhận bản sửa lỗi bằng cách chạy một bài kiểm tra CLI nhanh. Bạn sẽ thấy chữ "Done" mà không có bất kỳ cảnh báo nào đi kèm:

php -r 'class T { public $p; } $t = new T(); $t->p = 1; echo "Done";'

Nếu bạn đang sửa đổi các tệp hiện có, hãy luôn chạy kiểm tra lỗi cú pháp (lint check). Điều này đảm bảo bạn không vô tình đưa vào các lỗi cú pháp khi thêm các attribute:

php -l src/Models/User.php

Cuối cùng, hãy theo dõi log trực tiếp để đảm bảo tiếng ồn đã ngừng:

tail -f /var/log/php-fpm/error.log | grep "dynamic property"

Mẹo cho môi trường Production- Kiểm tra với PHPStan: Thiết lập mức độ phân tích tĩnh lên cấp 6 hoặc cao hơn. Nó sẽ gắn cờ mọi lần sử dụng thuộc tính động trước khi bạn chạm vào máy chủ.- Đừng che giấu vấn đề: Việc tắt E_DEPRECATED trong php.ini giống như dán băng dính đè lên đèn cảnh báo lỗi động cơ. Nó có tác dụng hôm nay, nhưng bạn sẽ đối mặt với sự cố nghiêm trọng khi PHP 9.0 ra mắt.- Kiểm tra các thư viện phụ thuộc: Nếu lỗi nằm trong thư mục vendor, hãy chạy composer update. Các framework lớn như Laravel và Symfony đã vá các vấn đề này từ nhiều tháng trước.

Related Error Notes