Lỗi nghiêm trọng của PHP: Sử dụng $ this khi không ở trong bối cảnh đối tượng


137

Tôi có một vấn đề:

Tôi đang viết một WebApp mới mà không có Framework.

Trong index.php của tôi, tôi đang sử dụng:require_once('load.php');

Và trong load.php Tôi đang sử dụng require_once('class.php');để tải class.php của mình .

Trong tôi class.php Tôi đã có lỗi này:

Lỗi nghiêm trọng: Sử dụng $ this khi không có trong ngữ cảnh đối tượng trong class.php trên dòng ... (trong ví dụ này sẽ là 11)

Một ví dụ về cách class.php của tôi được viết:

class foobar {

    public $foo;

    public function __construct() {
        global $foo;

        $this->foo = $foo;
    }

    public function foobarfunc() {
        return $this->foo();
    }

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

Trong index.php của tôi, tôi đang tải có thể foobarfunc()như thế này:

foobar::foobarfunc();

nhưng cũng có thể

$foobar = new foobar;
$foobar->foobarfunc();

Tại sao lỗi đến?


2
Thật trùng hợp, tôi đã vật lộn với lỗi này trong khoảng 3 giờ ngày hôm qua! :)
Jack

Câu trả lời:


184

Trong index.php của tôi, tôi đang tải có thể foobarfunc () như thế này:

 foobar::foobarfunc();  // Wrong, it is not static method

nhưng cũng có thể

$foobar = new foobar;  // correct
$foobar->foobarfunc();

Bạn không thể gọi phương thức theo cách này vì nó không phải là phương thức tĩnh.

foobar::foobarfunc();

Thay vào đó, bạn nên sử dụng:

foobar->foobarfunc();

Tuy nhiên, nếu bạn đã tạo một phương thức tĩnh, đại loại như:

static $foo; // your top variable set as static

public static function foo() {
    return self::$foo;
}

sau đó bạn có thể sử dụng điều này:

foobar::foobarfunc();

1
Các biến có cùng tên không phải là một vấn đề. $this->foolà một thành viên của lớp, trong khi $foochỉ là một biến trong phạm vi hàm (được nhập từ phạm vi toàn cầu). Tên hàm có cùng tên với thành viên cũng không phải là vấn đề.
Gordon

157
Bạn không thể sử dụng $thistrong một phương thức tĩnh.
Yacoby

5
Tuy nhiên, thật buồn cười khi một câu trả lời hoàn toàn sai lại được nêu lên. $ này không có sẵn trong ngữ cảnh lớp. OP sẽ nhận được cùng một lỗi từ ví dụ trên.
Gordon

4
@Sarfraz Không có hành vi phạm tội, nhưng nó vẫn sai. Bạn có thể gọi một phương thức ví dụ với ::. Đó là chống lại E_STRICT, nhưng nó không làm việc miễn là cơ thể phương pháp không tham chiếu tới phạm vi dụ, ví dụ như sử dụng $this. Ngoài ra, self::foosẽ không chỉ đến $this->foo. Nó tham chiếu một hằng số lớp . Cả hai, self::fooself::$foosẽ gây ra một lỗi nghiêm trọng.
Gordon

3
@Sarfraz bây giờ tốt hơn rồi. Xin lỗi vì đã làm phiền bạn, nhưng vì điều này đã trở thành câu trả lời được chấp nhận, tôi cảm thấy cần phải chỉ ra những điều này :) Cảm ơn vì sự kiên nhẫn của bạn.
Gordon

27

Bạn đang gọi một phương thức không tĩnh:

public function foobarfunc() {
    return $this->foo();
}

Sử dụng một cuộc gọi tĩnh:

foobar::foobarfunc();

Khi sử dụng lệnh gọi tĩnh, hàm sẽ được gọi (ngay cả khi không được khai báo là static) , nhưng, vì không có phiên bản của đối tượng, nên không có $this.

Vì thế :

  • Bạn không nên sử dụng các cuộc gọi tĩnh cho các phương thức không tĩnh
  • Các phương thức tĩnh của bạn (hoặc các phương thức được gọi là tĩnh) không thể sử dụng $ this, thường chỉ đến thể hiện hiện tại của lớp, vì không có cá thể lớp khi bạn đang sử dụng các cuộc gọi tĩnh.


Ở đây, các phương thức của lớp của bạn đang sử dụng thể hiện hiện tại của lớp, vì chúng cần truy cập vào thuộc $footính của lớp.

Điều này có nghĩa là các phương thức của bạn cần một thể hiện của lớp - có nghĩa là chúng không thể tĩnh.

Điều này có nghĩa là bạn không nên sử dụng các cuộc gọi tĩnh: bạn nên kích hoạt lớp và sử dụng đối tượng để gọi các phương thức, giống như bạn đã làm trong phần mã cuối cùng của mình:

$foobar = new foobar();
$foobar->foobarfunc();


Để biết thêm thông tin, đừng ngần ngại đọc, trong hướng dẫn sử dụng PHP:


Cũng lưu ý rằng bạn có thể không cần dòng này trong __constructphương thức của mình :

global $foo;

Sử dụng globaltừ khóa sẽ tạo ra $foobiến, được khai báo bên ngoài tất cả các hàm và lớp, hiển thị từ bên trong phương thức đó ... Và có lẽ bạn không có $foobiến như vậy .

Để truy cập thuộc tính $foo lớp , bạn chỉ cần sử dụng $this->foo, như bạn đã làm.


11

Nếu bạn đang gọi foobarfuncvới toán tử phạm vi độ phân giải ( ::), thì bạn đang gọi nó một cách tĩnh , ví dụ ở cấp độ lớp thay vì cấp độ cá thể, do đó bạn đang sử dụng $thiskhi không ở trong bối cảnh đối tượng . $thiskhông tồn tại trong bối cảnh lớp học.

Nếu bạn kích hoạt E_STRICT, PHP sẽ đưa ra một Thông báo về điều này:

Strict Standards: 
Non-static method foobar::foobarfunc() should not be called statically

Làm điều này thay thế

$fb = new foobar;
echo $fb->foobarfunc();

Trên một sidenote, tôi đề nghị không sử dụng globalbên trong các lớp học của bạn. Nếu bạn cần một cái gì đó từ bên ngoài bên trong lớp học của bạn, hãy chuyển nó qua hàm tạo. Điều này được gọi là Dependency Injection và nó sẽ làm cho mã của bạn dễ bảo trì hơn và ít phụ thuộc hơn vào những thứ bên ngoài.


6

Trước tiên, bạn hiểu một điều, $ this trong một lớp biểu thị đối tượng hiện tại .
Đó là bạn được tạo ra bên ngoài lớp để gọi hàm hoặc biến lớp.

Vì vậy, khi bạn đang gọi hàm lớp của mình như foobar :: foobarfunc (), đối tượng không được tạo. Nhưng bên trong hàm đó bạn đã viết return $ this-> foo (). Bây giờ ở đây $ này không có gì. Đó là lý do tại sao nó sử dụng $ this khi không có trong ngữ cảnh đối tượng trong class.php

Các giải pháp:

  1. Tạo một đối tượng và gọi foobarfunc ().

  2. Gọi foo () bằng tên lớp bên trong foobarfunc ().


2
hoặc chỉ sử dụng self :: thay vì $ this
Motassem MK

4

Khi bạn gọi hàm trong ngữ cảnh tĩnh, $thisđơn giản là không tồn tại.

Bạn sẽ phải sử dụng this::xyz()thay thế.

Để tìm hiểu bối cảnh bạn đang ở khi một chức năng có thể được gọi là tĩnh và trong một đối tượng, một cách tiếp cận tốt được nêu trong câu hỏi này: Làm thế nào để biết tôi tĩnh hay là một đối tượng?


4

Phương thức nhanh: (foobar mới ()) -> foobarfunc ();

Bạn cần tải lớp thay thế:

foobar::foobarfunc();

bởi:

(new foobar())->foobarfunc();

hoặc là :

$Foobar = new foobar();
$Foobar->foobarfunc();

Hoặc thực hiện chức năng tĩnh để sử dụng foobar::.

class foobar {
    //...

    static function foobarfunc() {
        return $this->foo();
    }
}

0

$foobar = new foobar;đặt lớp foobar trong $ foobar, không phải đối tượng . Để có được đối tượng, bạn cần thêm dấu ngoặc đơn:$foobar = new foobar();

Lỗi của bạn chỉ đơn giản là bạn gọi một phương thức trên một lớp, do đó không tồn tại $this$thischỉ tồn tại trong các đối tượng.


0

Nó dường như là một lỗi trong PHP. Lỗi

'Lỗi nghiêm trọng: Lỗi chưa được xử lý: Sử dụng $ this khi không ở trong bối cảnh đối tượng trong'

xuất hiện trong hàm bằng cách sử dụng $this, nhưng lỗi là hàm gọi đang sử dụng hàm không tĩnh làm tĩnh. I E:

Class_Name
{
    function foo()
    {
        $this->do_something(); // The error appears there.
    }
    function do_something()
    {
        ///
    }
}

Trong khi lỗi ở đây:

Class_Name::foo();

-2

Chỉ cần sử dụng phương thức Class bằng cách này foobar->foobarfunc();


2
Vui lòng chỉ trả lời các câu hỏi cũ nếu bạn có một cái gì đó mới để thêm.
Ajean
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.