Я проверяю некоторые PHP 5.3.0
функции и наткнулся на код на сайте, который выглядит довольно забавно:
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);
}
в качестве одного из примеров на анонимных функций .
Кто-нибудь знает об этом? Любая документация? И это выглядит злым, стоит ли его когда-либо использовать?
use
Ключевое слово также используется для наложения спектров пространств имен . Удивительно, что спустя более 3 лет после выпуска PHP 5.3.0 синтаксисfunction ... use
официально не документирован, что делает замыкания недокументированными. Документ даже смешивает анонимные функции и замыкания . Единственная (бета и неофициальная) документация, которуюuse ()
я смог найти на php.net, была RFC для закрытий .use
также используется для включенияtrait
вclass
!Более простой ответ.
function ($quantity) use ($tax, &$total) { .. };
$tax
внутри замыкания не имеет внешнего эффекта, если это не указатель, как у объекта.&$total
. Таким образом, изменяя значение$total
DOES HAVE , вы меняете значение исходной переменной.Как отметил @Mytskine , вероятно, лучшим подробным объяснением является RFC для замыканий . (Передайте ему голос за это.)
источник
$closure = function ($value) use ($localVar as $alias) { //stuff};
данная ошибка:Parse: syntax error, unexpected 'as' (T_AS), expecting ',' or ')'
&$total
имеет внутренний эффект. Другими словами, если вы измените значение за$total
пределами замыкания после того, как оно определено, новое значение будет передано, только если оно является указателем.global
того, что позволяет только доступ к глобальному пространству имен, тогда какuse
позволяет получить доступ к переменным в родительском пространстве имен. Глобальные переменные обычно считаются злыми. Доступ к родительской области часто является самой целью создания замыкания. Это не «зло», поскольку его возможности очень ограничены. Другие языки, такие как JS, неявно используют переменные родительской области видимости (как указатель, а не как скопированное значение).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.
Это
function () use () {}
как закрытие для PHP.Без
use
, функция не может получить доступ к родительской переменной областиЗначение
use
переменной берется с момента определения функции, а не при ее вызовеuse
переменная по ссылке с&
источник
крышки прекрасны! они решают множество проблем, связанных с анонимными функциями, и делают возможным действительно элегантный код (по крайней мере, пока мы говорим о php).
Программисты javascript используют замыкания все время, иногда даже не зная об этом, потому что связанные переменные не определены явно - вот для чего «использование» в php.
Есть лучшие примеры из реальной жизни, чем приведенный выше. Допустим, вам нужно отсортировать многомерный массив по значению, но ключ изменится.
предупреждение: непроверенный код (у меня не установлен php5.3 atm), но он должен выглядеть примерно так.
есть один недостаток: многие php-разработчики могут оказаться немного беспомощными, если вы столкнетесь с ними замыканиями.
Чтобы лучше понять замыкания замыканий, приведу еще один пример - на этот раз в javascript. Одной из проблем является асинхронность, присущая браузеру. особенно, если дело доходит до
window.setTimeout();
(или -интервала). Итак, вы передаете функцию в setTimeout, но вы не можете дать какие-либо параметры, потому что предоставление параметров выполняет код!myFunction возвращает функцию со своего рода предопределенным параметром!
честно говоря, мне больше нравится php с 5.3 и анонимные функции / замыкания. Пространства имен могут быть более важными, но они намного менее сексуальны .
источник
Zupa проделал большую работу, объясняя замыкания с помощью «use» и разницы между EarlyBinding и Referencing переменных, которые «используются».
Итак, я сделал пример кода с ранним связыванием переменной (= копирование):
Пример со ссылкой на переменную (обратите внимание на символ «&» перед переменной);
источник
До самых последних лет PHP определял свой AST, а интерпретатор PHP изолировал анализатор от части оценки. В то время, когда вводится замыкание, синтаксический анализатор PHP тесно связан с оценкой.
Поэтому, когда замыкание было впервые введено в PHP, у интерпретатора нет способа узнать, какие переменные будут использоваться в замыкании, поскольку оно еще не проанализировано. Таким образом, пользователь должен порадовать движок Zend явным импортом, выполняя домашнюю работу, которую должен сделать Zend.
Это так называемый простой способ в PHP.
источник