5.4.0 öncesi PHP'de anonim bir işlevde "$ this" kullanımı


86

PHP kılavuz durumları

$thisPHP 5.4.0'dan önce anonim işlevden kullanmak mümkün değildir.

üzerinde anonim fonksiyonlar sayfa . Ancak , fonksiyon tanımında $thisbir değişkene atayarak ve değişkeni bir useifadeye geçirerek onu çalıştırabileceğimi buldum .

$CI = $this;
$callback = function () use ($CI) {
    $CI->public_method();
};

Bu iyi bir uygulama mı? Anonim bir işlevin içine PHP 5.3 kullanarak
erişmenin daha iyi bir yolu var mı $this?


1
Sadece küçük bir forum kuralı - genellikle bir cevabı kabul etmek, tercih ettiğiniz cevabı yansıtacak şekilde bir soruyu düzenlemekten daha iyidir. Esasen bu, yanıtların kalıcılık açısından hala anlamlı olması ve tabii ki doğru yanıtın hakkını vermesi içindir.
halfer

4
Buna dikkat edin $CI = $this;ve aslında aynı $CI =& $this; değil . Belki amaçlarınız için, ama aynı değiller. $CI = 'bla'; var_dump($this);Farkı görmek için her iki sürümü de deneyin .
Rudie

1
@Rudie ben ekliyorum belgelerine Yorumlarınız için
steampowered

@steampowered Bununla ilgili bir yerde çevrimiçi olarak güzel bir örnek / makale var ama bulamadım =) Üzgünüm. Farkı görmüyorsanız sadece deneyin. Açık o zaman.
Rudie

Yanıtlar:


67

Üzerinde korumalı veya özel bir yöntemi çağırmaya çalıştığınızda başarısız olur, çünkü onu bu şekilde kullanmak dışarıdan arama olarak sayılır. Bildiğim kadarıyla 5.3'te bunu aşmanın bir yolu yok, ancak PHP 5.4 geliyor, kutudan çıktığı gibi beklendiği gibi çalışacak:

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}
$hello = new Hello();
$helloPrinter = $hello->createClosure();
$helloPrinter(); // outputs "Hello world"

Dahası, anonymus işlevleri için (kapatma yeniden bağlama) çalışma zamanında $ this'in işaret ettiği şeyi değiştirebileceksiniz:

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}

class Bye {

    private $message = "Bye world\n";

}

$hello = new Hello();
$helloPrinter = $hello->createClosure();

$bye = new Bye();
$byePrinter = $helloPrinter->bindTo($bye, $bye);
$byePrinter(); // outputs "Bye world"

Etkili bir şekilde, anonymus işlevleri bir bindTo () yöntemine sahip olacaktır ; burada birinci parametre $ this'in neyi işaret ettiğini belirtmek için kullanılabilir ve ikinci parametre görünürlük düzeyinin ne olması gerektiğini kontrol eder . İkinci parametreyi atlarsanız, görünürlük "dışarıdan" arama gibi olacaktır, örn. yalnızca genel mülklere erişilebilir. Ayrıca, bindTo'nun çalışma şeklini not edin, orijinal işlevi değiştirmez, yenisini döndürür .


1
Cevabınızı doğru olarak işaretlemek, ancak sadece diğer okuyucular için açıklığa kavuşturmak için: soruda kullanılan kural, referans veren nesneyi kullanan genel yöntemler için çalışacaktır $this.
steampowered

5
Halka açık olmayan yöntemlere yansıma kullanılarak erişilebilir. Verimsiz ve biraz kötü, ama işe yarıyor.
outis

7

Nesneleri referans olarak iletmek için her zaman PHP'ye güvenmeyin, kendisine bir referans atarken, davranış, orijinal göstericinin değiştirildiği çoğu OO dilindeki ile aynı değildir.

örneğiniz:

$CI = $this;
$callback = function () use ($CI) {
$CI->public_method();
};

olmalı:

$CI = $this;
$callback = function () use (&$CI) {
$CI->public_method();
};

NOT "&" REFERANSI ve $ CI, son çağrı yapıldıktan sonra atanmalıdır, aksi takdirde öngörülemeyen bir çıktıya sahip olabilirsiniz, PHP'de bir referansa erişim her zaman orijinal sınıfa erişmekle aynı değildir - eğer bu mantıklıysa.

http://php.net/manual/en/language.references.pass.php


6

Bu normal bir şekilde yapıldı.
btw, &nesneler herhangi bir şekilde ref tarafından geçtikçe, bu olmadan çalışması gerektiğini kaldırmaya çalışın .


1

Referans olarak geçmeniz, bunu yapmanın doğru yolu ise, sorun değil. PHP 5 kullanıyorsanız, &sembole $thisher zaman referansla geçeceği için önceden ihtiyacınız yoktur .


2
4.x anonim işlevleri desteklemediğinden OP 5.3 veya daha
üstünü

1

Bu iyi. Bunu da yapabileceğinizi düşünüyorum:

$CI = $this;

... çünkü nesneleri içeren atamalar her zaman tüm nesneleri değil referansları kopyalayacaktır.

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.