Błąd krytyczny PHP: użycie $ this, gdy nie jest w kontekście obiektu

142

Mam problem:

Piszę nową aplikację internetową bez Framework.

W moim index.php używam:require_once('load.php');

A w load.php używam require_once('class.php');do ładowania mojego class.php .

W moim class.php mam ten błąd:

Błąd krytyczny: użycie $ this bez kontekstu obiektu w class.php on-line ... (w tym przykładzie byłoby to 11)

Przykład, jak napisane jest moje class.php :

class foobar {

    public $foo;

    public function __construct() {
        global $foo;

        $this->foo = $foo;
    }

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

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

W moim index.php ładuję może foobarfunc()tak:

foobar::foobarfunc();

ale może też być

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

Dlaczego pojawia się błąd?

ahmet2106
źródło
2
Przypadkowo walczyłem z tym błędem wczoraj przez około 3 godziny! :)
Jack

Odpowiedzi:

195

W moim index.php ładuję być może foobarfunc () w ten sposób:

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

ale może też być

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

Nie możesz wywołać metody w ten sposób, ponieważ nie jest to metoda statyczna.

foobar::foobarfunc();

Zamiast tego powinieneś użyć:

foobar->foobarfunc();

Jeśli jednak utworzyłeś statyczną metodę, taką jak:

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

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

możesz użyć tego:

foobar::foobarfunc();
Sarfraz
źródło
1
Zmienne o tej samej nazwie nie stanowią problemu. $this->foojest $fooskładową klasy, a jest tylko zmienną w zakresie funkcji (importowaną z zasięgu globalnego). Nazwy funkcji o takiej samej nazwie jak członek również nie są problemem.
Gordon
167
Nie można używać $thisw metodzie statycznej.
Yacoby
5
To zabawne, jak całkowicie błędna odpowiedź zyskuje mimo wszystko głosy. $ this nie jest dostępne w kontekście klasy. OP otrzyma ten sam błąd, co w powyższym przykładzie.
Gordon,
4
@Sarfraz Bez obrazy, ale nadal jest źle. Państwo może wywołać metodę instancję ::. Jest przeciwko E_STRICT, ale nie pracować tak długo, jak ciało metoda nie odwoływać się do zakresu zastosowania instancji, np $this. Nie self::foobędzie też wskazywać $this->foo. Odwołuje się do stałej klasy . Oba self::fooi self::$foospowodowałoby błąd krytyczny.
Gordon
3
@Sarfraz jest teraz lepiej. Przepraszam, że cię męczyłem, ale ponieważ ta odpowiedź stała się akceptowana, uznałem za konieczne, aby zwrócić na to uwagę :) Dziękuję za cierpliwość.
Gordon
28

Wołasz metodę niestatyczną:

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

Korzystanie z wywołania statycznego:

foobar::foobarfunc();

Podczas korzystania z wywołania statycznego funkcja zostanie wywołana (nawet jeśli nie zostanie zadeklarowana jako static) , ale ponieważ nie ma instancji obiektu, nie ma $this.

Więc :

  • Nie należy używać wywołań statycznych dla metod niestatycznych
  • Twoje metody statyczne (lub metody nazywane statycznie) nie mogą używać $ this, co normalnie wskazuje na bieżące wystąpienie klasy, ponieważ nie ma instancji klasy, gdy używasz wywołań statycznych.


Tutaj metody Twojej klasy używają bieżącej instancji klasy, ponieważ muszą uzyskać dostęp do $foowłaściwości klasy.

Oznacza to, że Twoje metody wymagają instancji klasy - co oznacza, że ​​nie mogą być statyczne.

Oznacza to, że nie powinieneś używać wywołań statycznych: powinieneś zainicjować klasę i użyć obiektu do wywołania metod, tak jak to zrobiłeś w ostatniej części kodu:

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


Aby uzyskać więcej informacji, nie wahaj się przeczytać w podręczniku PHP:


Zauważ również, że prawdopodobnie nie potrzebujesz tego wiersza w swojej __constructmetodzie:

global $foo;

Użycie globalsłowa kluczowego sprawi, że $foozmienna, zadeklarowana poza wszystkimi funkcjami i klasami, będzie widoczna od wewnątrz tej metody ... I prawdopodobnie nie masz takiej $foozmiennej.

Aby uzyskać dostęp do $foo właściwości klasy , musisz tylko użyć $this->foo, tak jak zrobiłeś.

Pascal MARTIN
źródło
11

Jeśli wywołujesz foobarfuncz operatorem zakresu rozpoznawania ( ::), to wywołujesz go statycznie , np. Na poziomie klasy zamiast na poziomie instancji, więc używasz $thisgo poza kontekstem obiektu . $thisnie istnieje w kontekście klasowym.

Jeśli włączysz E_STRICT, PHP zgłosi powiadomienie o tym:

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

Zrób to zamiast tego

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

Na marginesie, sugeruję, aby nie używać ich podczas globalzajęć. Jeśli potrzebujesz czegoś spoza swojej klasy, prześlij to przez konstruktora. Nazywa się to wstrzykiwaniem zależności i sprawi, że twój kod będzie znacznie łatwiejszy w utrzymaniu i mniej zależny od rzeczy zewnętrznych.

Gordon
źródło
6

Najpierw zrozumiesz jedną rzecz, $ this wewnątrz klasy oznacza bieżący obiekt .
To znaczy, że jesteś utworzony poza klasą, aby wywołać funkcję lub zmienną klasy.

Więc kiedy wywołujesz funkcję klasy, taką jak foobar :: foobarfunc (), obiekt nie jest tworzony. Ale wewnątrz tej funkcji napisałeś return $ this-> foo (). Tutaj $ to nic. Dlatego mówi, używając $ this, gdy nie jest w kontekście obiektu w class.php

Rozwiązania:

  1. Utwórz obiekt i wywołaj foobarfunc ().

  2. Wywołaj foo () używając nazwy klasy wewnątrz foobarfunc ().

Ramasamy Kasi
źródło
2
lub po prostu użyj self :: zamiast $ this
Motassem MK
4

Kiedy wywołujesz funkcję w kontekście statycznym, $thispo prostu nie istnieje.

Zamiast tego musiałbyś użyć this::xyz().

Aby dowiedzieć się, w jakim kontekście się znajdujesz, gdy funkcję można wywołać zarówno statycznie, jak iw instancji obiektu, dobre podejście jest nakreślone w tym pytaniu: Jak stwierdzić, czy jestem statyczny, czy obiekt?

Pekka
źródło
4

Szybka metoda: (new foobar ()) -> foobarfunc ();

Musisz załadować zamianę klasy:

foobar::foobarfunc();

przez :

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

lub:

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

Lub użyj funkcji statycznejfoobar:: .

class foobar {
    //...

    static function foobarfunc() {
        return $this->foo();
    }
}
A-312
źródło
0

$foobar = new foobar;umieść klasę foobar w $ foobar, a nie obiekt . Aby pobrać obiekt, musisz dodać nawias:$foobar = new foobar();

Twój błąd polega po prostu na tym, że wywołujesz metodę na klasie, więc nie ma jej, $thisponieważ $thisistnieje tylko w obiektach.

e-satis
źródło
0

Wydaje mi się, że to błąd w PHP. Błąd

„Błąd krytyczny: nieprzechwycony błąd: użycie $ this, gdy nie jest w kontekście obiektu w”

pojawia się w funkcji using $this, ale błąd polega na tym, że funkcja wywołująca używa funkcji statycznej jako statycznej. To znaczy:

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

Podczas gdy błąd jest tutaj:

Class_Name::foo();
Yaakov Aglamaz
źródło
-1

Po prostu użyj metody Class, używając this foobar->foobarfunc();

Manobendronath Biswas
źródło
2
Odpowiadaj tylko na stare pytania, jeśli masz coś nowego do dodania.
Ajean