Sửa lỗi 'Non-static method should not be called statically' trong PHP 8

intermediate🐘 PHP2026-07-02| PHP 7.0+, PHP 8.0+ (Fatal Error), Linux/Windows, Apache/Nginx

Error Message

Fatal error: Uncaught Error: Non-static method User::getName() should not be called statically
#php#oop#static#web-development

Vấn đềTrong một đợt di chuyển từ PHP 7.4 lên 8.2 gần đây, tôi và đồng nghiệp đã gặp bế tắc với một mã nguồn cũ (legacy codebase). Trong khi trang chủ tải hoàn hảo, bảng điều khiển người dùng lại bị sập ngay lập tức. Nhật ký lỗi (error logs) đã chỉ ra thủ phạm:

Fatal error: Uncaught Error: Non-static method User::getName() should not be called statically

Trong kỷ nguyên PHP 5.6 và 7.x, sai lầm này thường chỉ kích hoạt cảnh báo Deprecated hoặc Notice. Script của bạn vẫn tiếp tục chạy bất chấp mã nguồn lộn xộn. Tuy nhiên, kể từ khi PHP 8.0 ra mắt vào tháng 11 năm 2020, lỗi này đã được nâng cấp thành Fatal Error. Nó sẽ khiến ứng dụng của bạn dừng hoạt động ngay lập tức.

Tại sao điều này xảy raLỗi này xảy ra khi bạn sử dụng cú pháp dấu hai chấm kép (Class::method()) cho một phương thức không được định nghĩa với từ khóa static. Trong Lập trình hướng đối tượng (OOP), các phương thức non-static thuộc về một thể hiện (instance) cụ thể (một đối tượng), trong khi các phương thức static thuộc về chính định nghĩa lớp (class definition).

Dưới đây là một đoạn mã sẽ làm hỏng trang web của bạn trong PHP 8:

class User {
    public function getName() {
        return "John Doe";
    }
}

// Lệnh này kích hoạt Fatal Error trong PHP 8.0+
echo User::getName();

Cách khắc phụcBạn có hai cách chính để giải quyết vấn đề này, tùy thuộc vào việc phương thức đó có cần truy cập dữ liệu nội bộ của đối tượng hay không.

Cách 1: Khởi tạo lớp (Tốt nhất cho dữ liệu thể hiện)Nếu phương thức của bạn sử dụng $this để truy cập các thuộc tính, bạn phải tạo một đối tượng trước. Đây là cách tiếp cận tiêu chuẩn cho các domain model và hầu hết các logic ứng dụng.

class User {
    private $name = "John Doe";

    public function getName() {
        return $this->name;
    }
}

// Cách đúng: Tạo đối tượng, sau đó gọi phương thức
$user = new User();
echo $user->getName();

Cách 2: Khai báo phương thức là StaticSử dụng cách này nếu phương thức là một hàm bổ trợ (helper function) "thuần túy" không phụ thuộc vào bất kỳ trạng thái nội bộ nào của đối tượng. Bằng cách thêm từ khóa static, bạn báo cho PHP rằng phương thức này có thể được gọi trực tiếp từ lớp.

class User {
    public static function getName() {
        return "John Doe";
    }
}

// Lệnh này hiện đã hoàn toàn hợp lệ
echo User::getName();

Cảnh giác với "bẫy" $thisHãy cẩn thận khi chọn Cách 2. Nếu bạn thêm từ khóa static vào một phương thức vẫn chứa $this, bạn sẽ ngay lập tức kích hoạt một lỗi khác: Uncaught Error: Using $this when not in object context. Các phương thức static không có khái niệm về "chính mình" (self) trong một thể hiện. Nếu bạn cần các thuộc tính đó, hãy kiên trì với Cách 1.

Xử lý các lệnh gọi lớp cha (Parent Class)Mã nguồn cũ thường kích hoạt lỗi này trong quá trình kế thừa. Bạn chỉ có thể gọi một phương thức cha non-static bằng cú pháp giống như static nếu bạn đang ở bên trong một phương thức con non-static.

class Base {
    public function log() { /* ... */ }
}

class Child extends Base {
    public function doWork() {
        // Lệnh này hoạt động vì doWork() cũng là non-static
        parent::log(); 
    }
}

Kiểm tra kết quảKiểm tra bản sửa lỗi của bạn bằng cách chạy script qua CLI hoặc tải lại trình duyệt. Để phát hiện các vấn đề này trước khi đưa lên môi trường production, hãy thiết lập báo cáo lỗi ở mức cao nhất trong tệp php.ini của bạn:

error_reporting(E_ALL);
ini_set('display_errors', 1);

Nếu trang hiển thị mà không có Fatal Error và dữ liệu xuất hiện chính xác, bạn đã thành công.

Kết luận chính- PHP 8 rất nghiêm ngặt: Những gì từng là cảnh báo nhỏ giờ là lỗi làm sập trang web. Luôn kiểm tra nhật ký sau khi nâng cấp.- Cú pháp rất quan trọng: Sử dụng -> cho các đối tượng và :: cho các lớp static. Việc trộn lẫn chúng là nguồn cơn chính của nợ kỹ thuật (technical debt).- Hãy để IDE hỗ trợ: Các công cụ như PHPStorm hoặc VS Code với tiện ích mở rộng Intelephense sẽ làm nổi bật các lệnh gọi không hợp lệ này bằng màu đỏ ngay khi bạn gõ phím.

Related Error Notes