PHP Ölümcül hatası: Nesne bağlamında değilken $ this kullanılması


138

Bir problemim var:

Framework olmadan yeni bir WebApp yazıyorum.

Benim içinde index.php kullanıyorum:require_once('load.php');

Ve de load.php kullanıyorum require_once('class.php');benim yük class.php .

Benim içinde class.php bu hatayı var:

Ölümcül hata: satırdaki class.php'de nesne bağlamında değilken $ this kullanılması ... (bu örnekte 11 olacaktır)

Class.php dosyamın nasıl yazıldığına bir örnek :

class foobar {

    public $foo;

    public function __construct() {
        global $foo;

        $this->foo = $foo;
    }

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

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

Benim içinde index.php belki yükleme ediyorum foobarfunc()böyle:

foobar::foobarfunc();

ama aynı zamanda olabilir

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

Hata neden geliyor?


2
Tesadüfen dün bu hatayla yaklaşık 3 saat uğraşıyordum! :)
Jack

Yanıtlar:


184

İndex.php dosyamda belki foobarfunc () 'ı şöyle yüklüyorum:

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

ama aynı zamanda olabilir

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

Statik bir yöntem olmadığı için yöntemi bu şekilde çağıramazsınız.

foobar::foobarfunc();

Bunun yerine şunu kullanmalısınız:

foobar->foobarfunc();

Bununla birlikte, aşağıdaki gibi bir statik yöntem oluşturduysanız:

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

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

o zaman bunu kullanabilirsiniz:

foobar::foobarfunc();

1
Aynı isme sahip değişkenler bir sorun değildir. $this->foobir sınıf üyesidir, ancak $fooişlev kapsamındaki bir değişkendir (genel kapsamdan içe aktarılır). Bir üye ile aynı isme sahip fonksiyon isimleri de sorun teşkil etmez.
Gordon

157
$thisStatik bir yöntemde kullanamazsınız .
Yacoby

5
Yine de tamamen yanlış bir cevabın olumlu oylar alması komik. $ bu, sınıf bağlamında kullanılamaz. OP, yukarıdaki örnekten aynı hatayı alacaktır.
Gordon

4
@Sarfraz Alınma ama yine de yanlış. Sen edebilir bir örnek yöntemini çağırın ::. Bu karşıdır E_STRICT, ama does uzun yöntem vücut, örneğin kullanımları örnek kapsamını başvuru yapmıyor gibi işi $this. Ayrıca, self::fooişaret etmeyecek $this->foo. Bir sınıf sabitine başvurur . Her ikisi de self::foove self::$fooÖlümcül Hata ortaya çıkarır.
Gordon

3
@Sarfraz şimdi daha iyi. Rahatsız ettiğim için özür dilerim, ama bu kabul edilen cevap haline geldiğinden, bunları belirtmem gerektiğini hissettim :) Sabrınız için teşekkürler.
Gordon

27

Statik olmayan bir yöntem çağırıyorsunuz:

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

Statik çağrı kullanma:

foobar::foobarfunc();

Statik bir çağrı kullanırken, işlev çağrılacaktır (olarak bildirilmemiş olsa bile static) , ancak bir nesnenin bir örneği olmadığı için, bir de yoktur $this.

Yani :

  • Statik olmayan yöntemler için statik çağrılar kullanmamalısınız
  • Statik yöntemleriniz (veya statik olarak adlandırılan yöntemler), statik çağrıları kullanırken sınıf örneği olmadığından, normalde sınıfın geçerli örneğini gösteren $ this kullanamaz.


Burada, sınıfınızın yöntemleri, sınıfın $fooözelliğine erişmeleri gerektiğinden, sınıfın geçerli örneğini kullanır .

Bu, yöntemleriniz için sınıfın bir örneğine ihtiyaç duyduğu anlamına gelir - bu, statik olamayacakları anlamına gelir.

Bu, statik çağrılar kullanmamanız gerektiği anlamına gelir: kodun son bölümünde yaptığınız gibi, sınıfı kaydetmeli ve nesneyi yöntemleri çağırmak için kullanmalısınız:

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


Daha fazla bilgi için, PHP kılavuzunu okumaktan çekinmeyin:


Ayrıca __constructyönteminizde muhtemelen bu satıra ihtiyacınız olmadığını unutmayın :

global $foo;

globalAnahtar sözcüğü kullanmak $foodeğişkeni, tüm işlevlerin ve sınıfların dışında bildirilmiş, bu yöntemin içinden görünür hale getirecektir ... Ve muhtemelen böyle bir $foodeğişkeniniz yok.

$foo Sınıf özelliğine erişmek için , yaptığınız gibi yalnızca kullanmanız gerekir $this->foo.


11

Eğer yürütmesini ise foobarfuncile çözünürlüklü kapsam operatörü ( ::), o zaman aradığınız statik böylece edilir, sınıf düzeyine yerine örneği düzeyinde örneğin kullanırken $thisdeğilken nesne bağlamında . $thissınıf bağlamında mevcut değil.

Etkinleştirirseniz E_STRICT, PHP bununla ilgili bir Bildirim oluşturur:

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

Bunun yerine bunu yap

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

Bir yan notta globalderslerinizin içinde kullanmamanızı öneririm . Sınıfınızın içinde dışarıdan bir şeye ihtiyacınız varsa, bunu kurucuya iletin. Buna Bağımlılık Enjeksiyonu denir ve kodunuzu çok daha sürdürülebilir hale getirecek ve dışarıdaki şeylere daha az bağımlı hale getirecektir.


6

İlk önce bir şeyi anlarsınız, bir sınıfın içindeki $ this mevcut nesneyi belirtir .
Bu, sınıf işlevini veya değişkenini çağırmak için sınıfın dışında yaratıldığınız şeydir.

Yani foobar :: foobarfunc () gibi sınıf işlevinizi çağırdığınızda, nesne yaratılmaz. Ama bu fonksiyonun içinde yazdığınız $ this-> foo () döndür. Şimdi burada $ bu hiçbir şey değil. Bu yüzden class.php'de nesne bağlamında değilken $ this kullanılıyor diyor

Çözümler:

  1. Bir nesne oluşturun ve foobarfunc () öğesini çağırın.

  2. Foobarfunc () içindeki sınıf adını kullanarak foo () çağırın.


2
veya $ this yerine self :: kullanın
Motassem MK

4

Fonksiyonu statik bir bağlamda çağırdığınızda, $thissadece mevcut değildir.

Bunun this::xyz()yerine kullanmanız gerekir .

Bir işlev hem durağan olarak hem de bir nesne örneğinde çağrılabildiğinde hangi bağlamda olduğunuzu bulmak için, bu soruda iyi bir yaklaşım özetlenmiştir: Durağan mı yoksa nesne mi olduğumu nasıl anlarım?


4

Hızlı yöntem: (new foobar ()) -> foobarfunc ();

Sınıf değişiminizi yüklemeniz gerekir:

foobar::foobarfunc();

tarafından :

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

veya:

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

Veya kullanmak için statik işlevi yapın foobar::.

class foobar {
    //...

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

0

$foobar = new foobar;sınıf foobarını nesneye değil, $ foobar'a koyun . Nesneyi elde etmek için parantez eklemeniz gerekir:$foobar = new foobar();

Sizin hata dolayısıyla orada, bir sınıfın bir yöntem dediğimiz basitçe $thisberi $thissadece nesneler bulunmaktadır.


0

Bana PHP'de bir hata gibi görünüyor. Hata

'Önemli hata: Yakalanmamış Hata: $ this konumunda nesne bağlamında değilken kullanılıyor'

kullanan işlevde görünür $this, ancak hata, çağıran işlevin statik olmayan işlevi kullanmasıdır. yani:

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

Hata buradayken:

Class_Name::foo();

-2

Sadece bunu kullanarak Sınıf yöntemini kullanın foobar->foobarfunc();


2
Lütfen yalnızca ekleyecek yeni bir şeyiniz varsa eski soruları yanıtlayın .
Ajean
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.