Estoy revisando algunas PHP 5.3.0
características y encontré un código en el sitio que parece bastante divertido:
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);
}
como uno de los ejemplos sobre funciones anónimas .
¿Alguien sabe sobre esto? Cualquier documentación? Y se ve malvado, ¿debería alguna vez usarse?
use
palabra clave también se usa para crear alias de espacios de nombres . Es sorprendente que, más de 3 años después del lanzamiento de PHP 5.3.0, la sintaxisfunction ... use
todavía esté oficialmente indocumentada, lo que hace que los cierres sean una característica indocumentada. El documento incluso confunde funciones anónimas y cierres . La única documentación (beta y no oficial)use ()
que pude encontrar en php.net fue el RFC para cierres .use
también se usa para incluir untrait
en unclass
!Una respuesta más simple.
function ($quantity) use ($tax, &$total) { .. };
$tax
dentro del cierre no tiene efecto externo, a menos que sea un puntero, como lo es un objeto.&$total
. De esta manera, modificando el valor de$total
TIENE UN efecto externo, el valor de la variable original cambia.Como señaló @Mytskine , probablemente la mejor explicación en profundidad es el RFC para cierres . (Votéalo por esto).
fuente
$closure = function ($value) use ($localVar as $alias) { //stuff};
error dado es:Parse: syntax error, unexpected 'as' (T_AS), expecting ',' or ')'
&$total
tiene un efecto interno. En otras palabras, si cambia el valor de$total
fuera del cierre después de que se define, el nuevo valor solo se transfiere si es un puntero.global
solo permite el acceso al espacio de nombres global mientras queuse
permite el acceso a las variables en el espacio de nombres padre. Las variables globales generalmente se consideran malvadas. Acceder al ámbito principal es a menudo el propósito de crear un cierre. No es "malvado" ya que su alcance es muy limitado. Otros lenguajes como JS utilizan implícitamente las variables del ámbito primario (como puntero, no como valor copiado).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.
El
function () use () {}
es como el cierre para PHP.Sin
use
, la función no puede acceder a la variable de ámbito principalEl
use
valor de la variable es de cuando se define la función, no cuando se llamause
por referencia variable con&
fuente
los cierres son hermosos! resuelven muchos problemas que vienen con funciones anónimas y hacen posible un código realmente elegante (al menos mientras hablemos de php).
los programadores de javascript usan cierres todo el tiempo, a veces incluso sin saberlo, porque las variables enlazadas no están explícitamente definidas, para eso sirve "uso" en php.
Hay mejores ejemplos del mundo real que el anterior. supongamos que tiene que ordenar una matriz multidimensional por un subvalor, pero la clave cambia.
advertencia: código no probado (no tengo php5.3 instalado atm), pero debería parecerse a algo así.
Hay un inconveniente: muchos desarrolladores de PHP pueden ser un poco indefensos si los confrontas con cierres.
Para comprender mejor la simplicidad de los cierres, te daré otro ejemplo, esta vez en javascript. Uno de los problemas es el alcance y la asincronía inherente al navegador. especialmente, si se trata de
window.setTimeout();
(o -intervalo). entonces, pasa una función a setTimeout, pero realmente no puede dar ningún parámetro, ¡porque proporcionar parámetros ejecuta el código!¡myFunction devuelve una función con un tipo de parámetro predefinido!
para ser honesto, me gusta mucho más php desde 5.3 y funciones / cierres anónimos. Los espacios de nombres pueden ser más importantes, pero son mucho menos sensuales .
fuente
Zupa hizo un gran trabajo al explicar los cierres con 'uso' y la diferencia entre EarlyBinding y Referenciar las variables que se 'usan'.
Así que hice un ejemplo de código con enlace temprano de una variable (= copia):
Ejemplo con referencia a una variable (observe el carácter '&' antes de la variable);
fuente
Hasta años muy recientes, PHP ha definido su intérprete AST y PHP ha aislado el analizador de la parte de evaluación. Durante el tiempo en que se introduce el cierre, el analizador de PHP está altamente asociado con la evaluación.
Por lo tanto, cuando el cierre se introdujo por primera vez en PHP, el intérprete no tiene ningún método para saber qué variables se usarán en el cierre, porque aún no se ha analizado. Por lo tanto, el usuario debe complacer al motor zend mediante la importación explícita, haciendo los deberes que debe hacer zend.
Esta es la llamada forma simple en PHP.
fuente