Menu

Funciones anónimas y closures en PHP: la palabra clave use

Una función anónima (closure) es una función sin nombre guardada en una variable: $greet = function ($name) { return "Hi $name"; };. Aprende la palabra clave use, la captura por referencia, los callables, la sintaxis de callable de primera clase strlen(...) y los closures dentro de clases.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Una función anónima, también llamada closure, es una función sin nombre. Escribes function ($param) { ... } donde se espera un valor: la asignas a una variable, la pasas a otra función o la devuelves. Puede llevar consigo variables del código que la rodea con use ($var).

Toda función anónima es un objeto de la clase nativa Closure, y por eso se puede guardar, pasar de un sitio a otro y llamar más tarde con $greet(...).

La palabra clave use captura por valor

Un closure no puede ver por sí solo las variables de fuera. use ($x) copia el valor de $x dentro del closure en el momento en que se crea el closure, no cuando se ejecuta:

use por referencia: &$var

use (&$x) le da al closure la propia variable en lugar de una copia. Los cambios hechos dentro del closure se ven fuera, y los hechos fuera se ven dentro. Así es como un callback suma a un total o mantiene un contador.

Cada llamada a makeCounter() crea un $count nuevo, y el closure devuelto lo mantiene vivo después de que la función haya terminado. A eso se refiere "closure": la función encierra las variables que necesita.

Pasar un closure como callback

Funciones como array_map(), array_filter(), usort() y array_walk() reciben una función como argumento. Un closure te permite escribirla en el sitio, con tantas sentencias como necesite el trabajo:

Cuando el cuerpo es una sola expresión, una función flecha como fn($p) => $p['price'] es más corta y no necesita use.

Callables: nombres de funciones, métodos y strlen(...)

Un parámetro con el tipo callable acepta más que closures. Cuentan una cadena con el nombre de una función, un array con un objeto y el nombre de un método, y un array con el nombre de una clase y el de un método estático. Desde PHP 8.1, la sintaxis de callable de primera clase strlen(...) convierte cualquiera de ellos directamente en un Closure.

La forma (...) se comprueba cuando se ejecuta la línea: una errata lanza un Error ahí mismo. Una cadena como 'strtoupr' es solo una cadena hasta que alguien intenta llamarla.

Closures dentro de una clase: $this y static

Un closure creado dentro de un método tiene $this vinculado automáticamente, así que puede usar las propiedades del objeto. Márcalo como static function cuando no necesite $this, lo que además evita que mantenga vivo el objeto.

Olvidar use

El bug más común con closures es usar una variable de fuera sin listarla en use. Dentro del closure, la variable no existe:

$minAge = 18;
$adults = array_filter($people, function ($p) {
    return $p['age'] >= $minAge;   // $minAge is not in use (...)
});
PHP prints: Warning: Undefined variable $minAge

$minAge vale null dentro, cualquier edad comparada >= null es true y todas las personas pasan el filtro. En un servidor que oculta los warnings, nada te avisa. Añade la variable a use:

Preguntas frecuentes

¿Qué es un closure en PHP?

Una función sin nombre, creada con function (...) { ... } y guardada en una variable o pasada como argumento. PHP la representa como un objeto de la clase Closure. Puede llevar consigo variables del ámbito donde se creó, listadas en use (...).

¿Qué hace la palabra clave use en un closure de PHP?

use ($x) copia la variable exterior $x dentro del closure cuando se crea el closure. Los cambios posteriores a $x fuera no se ven. Escribe use (&$x) para compartir la variable, de modo que los cambios vayan en las dos direcciones.

¿Qué es un callable en PHP?

Cualquier cosa que PHP pueda llamar: un closure, el nombre de una función como cadena ('strtoupper'), un array [$object, 'method'] o [ClassName::class, 'staticMethod'], o un objeto con __invoke(). Usa el tipo callable para aceptar cualquiera de ellos e is_callable() para comprobarlo.

¿Qué significa strlen(...) en PHP?

Es la sintaxis de callable de primera clase de PHP 8.1: strlen(...) crea un Closure a partir de la función sin llamarla. También funciona con métodos, $obj->method(...), y con métodos estáticos, Foo::bar(...), y se comprueba cuando se ejecuta la línea, a diferencia de un nombre en una cadena.

¿Necesito un punto y coma después de una función anónima?

Sí, cuando la asignas: $f = function () { ... }; es una sentencia de asignación, así que termina en ;. Omitirlo es un error de sintaxis. Un closure pasado directamente como argumento no necesita su propio punto y coma.

Ilustración de los lenguajes de programación de Coddy

Aprende a programar con Coddy

COMENZAR