Sprawdzam niektóre PHP 5.3.0
funkcje i natknąłem się na kod na stronie, który wygląda dość zabawnie:
public function getTotal($tax)
{
$total = 0.00;
$callback =
/* This line here: */
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);
return round($total, 2);
}
jako jeden z przykładów funkcji anonimowych .
Czy ktoś o tym wie? Jakaś dokumentacja? I wygląda źle, czy należy go kiedykolwiek użyć?
use
kluczowe służy również do aliasingu przestrzeni nazw . To niesamowite, że ponad 3 lata po wydaniu PHP 5.3.0 składniafunction ... use
jest nadal oficjalnie nieudokumentowana, co powoduje, że zamknięcia są nieudokumentowaną funkcją. Dokument nawet myli anonimowe funkcje i zamknięcia . Jedyną (beta i nieoficjalną) dokumentacją,use ()
którą mogłem znaleźć na php.net, była RFC dla zamknięć .use
jest również używany do włączenia atrait
doclass
!Prostsza odpowiedź.
function ($quantity) use ($tax, &$total) { .. };
$tax
wewnątrz zamknięcia nie ma efektu zewnętrznego, chyba że jest wskaźnikiem, tak jak obiekt.&$total
. W ten sposób, modyfikując wartość$total
DOES MAJĄ efekt zewnętrzny, zmienia się wartość oryginalnej zmiennej.Jak zauważył @Mytskine , prawdopodobnie najlepszym dogłębnym wyjaśnieniem jest RFC dla zamknięć . (Głosuj za to.)
źródło
$closure = function ($value) use ($localVar as $alias) { //stuff};
Parse: syntax error, unexpected 'as' (T_AS), expecting ',' or ')'
&$total
ma również efekt wewnętrzny. Innymi słowy, jeśli zmienisz wartość$total
poza zamknięciem po jej zdefiniowaniu, nowa wartość zostanie przekazana tylko wtedy, gdy będzie wskaźnikiem.global
pozwala jedynie na dostęp do globalnej przestrzeni nazwuse
umożliwia dostęp do zmiennych w nadrzędnej przestrzeni nazw. Zmienne globalne są ogólnie uważane za złe. Dostęp do zakresu nadrzędnego jest często właśnie celem utworzenia zamknięcia. Nie jest to „zło”, ponieważ jego zakres jest bardzo ograniczony. Inne języki, takie jak JS, domyślnie używają zmiennych zakresu nadrzędnego (jako wskaźnik, a nie jako skopiowana wartość).You can pass in variables as pointers like in case of &$total. This way, modifying the value of $total DOES HAVE an external effect, the original variable's value changes.
To
function () use () {}
jest jak zamknięcie PHP.Bez
use
funkcji funkcja nie może uzyskać dostępu do zmiennej zasięgu nadrzędnegoWartość
use
zmiennej pochodzi z momentu zdefiniowania funkcji, a nie z jej wywołaniause
zmienna referencja za pomocą&
źródło
zamknięcia są piękne! rozwiązują wiele problemów związanych z funkcjami anonimowymi i umożliwiają naprawdę elegancki kod (przynajmniej tak długo, jak mówimy o php).
programiści javascript używają zamknięć przez cały czas, czasem nawet nie wiedząc o tym, ponieważ zmienne powiązane nie są wyraźnie zdefiniowane - po to właśnie jest „use” w php.
istnieją lepsze przykłady z prawdziwego świata niż powyższy. powiedzmy, że musisz posortować tablicę wielowymiarową według podwartości, ale klucz się zmienia.
ostrzeżenie: nieprzetestowany kod (nie mam zainstalowanego bankomatu php5.3), ale powinien on wyglądać tak.
ma jedną wadę: wielu programistów php może być nieco bezradnych, jeśli skonfrontujesz ich z zamknięciami.
aby lepiej zrozumieć wygodę zamykania, dam wam inny przykład - tym razem w javascript. jednym z problemów jest zakres i nieodłączna asynchroniczność przeglądarki. zwłaszcza jeśli chodzi o
window.setTimeout();
(lub -interval). więc przekazujesz funkcję do setTimeout, ale tak naprawdę nie możesz podać żadnych parametrów, ponieważ podanie parametrów powoduje wykonanie kodu!myFunction zwraca funkcję z rodzajem predefiniowanego parametru!
szczerze mówiąc, bardziej lubię php od 5.3 i anonimowe funkcje / zamknięcia. przestrzenie nazw mogą być ważniejsze, ale są o wiele mniej seksowne .
źródło
Zupa wykonała świetną robotę, wyjaśniając zamknięcia za pomocą „use” i różnicy między EarlyBinding i Odwoływaniem się do zmiennych, które są „używane”.
Zrobiłem więc przykładowy kod z wczesnym wiązaniem zmiennej (= kopiowanie):
Przykład z odwołaniem się do zmiennej (zwróć uwagę na znak „&” przed zmienną);
źródło
Do ostatnich lat PHP definiowało AST, a interpreter PHP izolował parser od części ewaluacyjnej. Podczas wprowadzania zamknięcia parser PHP jest bardzo sprzężony z oceną.
Dlatego, kiedy zamknięcie zostało po raz pierwszy wprowadzone w PHP, interpreter nie ma metody, która wiedziałaby, które zmienne zostaną użyte w zamknięciu, ponieważ nie jest jeszcze analizowane. Użytkownik musi zadowolić silnik Zend poprzez wyraźne importowanie, wykonując zadanie domowe, które powinien wykonać Zend.
Jest to tak zwany prosty sposób w PHP.
źródło