2011-12-05 11 views
80

PZP stany ręcznych

Nie jest możliwe użycie $this z funkcji anonimowej przed PHP 5.4.0

na anonymous functions page. Ale odkryłem, że mogę sprawić, że zadziała, przypisując $this do zmiennej i przekazując zmienną do instrukcji use w definicji funkcji.

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

Czy to dobra praktyka?
Czy istnieje lepszy sposób uzyskania dostępu do $this w anonimowej funkcji przy użyciu PHP 5.3?

+1

tylko drobne konwencja forum - jest to zwykle lepiej przyjąć odpowiedź niż edytować pytanie do zastanowienia się preferowaną odpowiedź. Przede wszystkim dlatego, że odpowiedzi wciąż mają sens na wieczność, ale także oczywiście w celu uznania poprawnej odpowiedzi. – halfer

+3

Pamiętaj, że '$ CI = $ this;' i '$ CI = & $ this; ** nie są właściwie identyczne. Może dla twoich celów, ale to nie to samo. Wypróbuj '$ CI = 'bla'; var_dump ($ this); 'w obu wersjach, aby zobaczyć różnicę. – Rudie

+1

@Rudie Dodaję [dokumentację] (http://php.net/manual/en/language.oop5.references.php) do Twojego komentarza – steampowered

Odpowiedz

61

Nie powiedzie się, gdy spróbujesz wywołać metodę chronioną lub prywatną, ponieważ używanie jej w ten sposób jest traktowane jako połączenie z zewnątrz. Nie ma sposobu, aby obejść ten problem w 5.3, o ile mi wiadomo, ale pochodzą z PHP 5.4, to będzie działać zgodnie z oczekiwaniami, po wyjęciu z pudełka:

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" 

Nawet więcej, będzie w stanie zmienić tego, co $ wskazuje to na starcie, dla funkcji Anonima (ponownego wiązania zamknięcia):

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" 

Skutecznie, funkcje anonimowym będzie miał bindTo() method, gdzie pierwszy parametr może być wykorzystany do określenia, co $ this punktów, a drugi kontroli parametrów jaki powinien być poziom widoczności:. Jeśli pominiesz drugi parametr, widoczność będzie jak wywołanie z "zewnątrz", np. dostępne są tylko właściwości publiczne. Zanotuj także sposób działania bindTo, nie modyfikuj oryginalnej funkcji, zwraca nowy.

+1

Oznaczanie poprawnej odpowiedzi, ale tylko w celu wyjaśnienia innych czytelników: konwencja użyte w pytaniu będzie działać dla publicznych metod używających obiektu, który odwołuje się do '$ this'. – steampowered

+5

[Metody niepubliczne] (http://stackoverflow.com/a/6386863/90527) można uzyskać za pomocą refleksji. Nieefektywny i trochę zły, ale działa. – outis

1

To wydaje się być w porządku, jeśli przekazanie przez odniesienie jest prawidłowym sposobem. Jeśli używasz PHP 5, nie potrzebujesz symbolu & przed $this, ponieważ zawsze będzie on przekazywany niezależnie.

+2

Program operacyjny musi być w wersji 5.3 lub nowszej, ponieważ 4.x nie obsługuje anonimowych funkcji :-) – halfer

1

To jest w porządku. Myślę, że możesz to zrobić:

$CI = $this; 

... ponieważ przypisania z obiektami zawsze będą kopiować odniesienia, a nie całe obiekty.

5

To jest normalny sposób, w jaki zostało to zrobione.
b.t.w, spróbuj usunąć & powinien działać bez tego, ponieważ obiekty przechodzą przez ref w żaden sposób.

5

Nie zawsze polegaj na PHP, aby przekazywać obiekty przez odniesienie, podczas przypisywania samego odniesienia, zachowanie nie jest takie samo, jak w większości języków OO, w których oryginalny wskaźnik jest modyfikowany.

Twój przykład:

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

powinno być:

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

UWAGA odniesienie „&” i $ CI należy przypisać po wywołań końcowych na to zostało zrobione, znowu inny może masz nieprzewidywalne dane wyjściowe, w PHP dostęp do odniesienia nie zawsze jest taki sam jak dostęp do oryginalnej klasy - jeśli ma to sens.

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

Powiązane problemy