Menu

Funções anônimas e closures no PHP: a palavra-chave use

Uma função anônima (closure) é uma função sem nome guardada numa variável: $greet = function ($name) { return "Hi $name"; };. Veja a palavra-chave use, captura por referência, callables, a sintaxe de callable de primeira classe strlen(...) e closures dentro de classes.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Uma função anônima, também chamada de closure, é uma função sem nome. Você escreve function ($param) { ... } onde um valor é esperado: atribui a uma variável, passa para outra função ou retorna. Ela pode levar variáveis do código em volta com use ($var).

Toda função anônima é um objeto da classe nativa Closure, e é por isso que ela pode ser guardada, passada adiante e chamada depois com $greet(...).

A palavra-chave use captura por valor

Uma closure não enxerga variáveis de fora sozinha. use ($x) copia o valor de $x para dentro da closure no momento em que a closure é criada, não quando ela roda:

use por referência: &$var

use (&$x) dá à closure a própria variável em vez de uma cópia. Mudanças dentro da closure são visíveis fora, e mudanças fora são vistas dentro. É assim que um callback soma num total ou mantém um contador.

Cada chamada a makeCounter() cria um novo $count, e a closure retornada o mantém vivo depois que a função retornou. É a isso que "closure" se refere: a função se fecha sobre as variáveis de que precisa.

Passar uma closure como callback

Funções como array_map(), array_filter(), usort() e array_walk() recebem uma função como argumento. Uma closure deixa você escrevê-la no lugar, com quantas instruções a tarefa precisar:

Quando o corpo é uma única expressão, uma arrow function como fn($p) => $p['price'] é mais curta e não precisa de use.

Callables: nomes de funções, métodos e strlen(...)

Um parâmetro com o tipo callable aceita mais que closures. Uma string com o nome de uma função, um array com um objeto e o nome de um método, e um array com um nome de classe e um método estático, todos contam. Desde o PHP 8.1, a sintaxe de callable de primeira classe strlen(...) transforma qualquer um deles diretamente numa Closure.

A forma (...) é verificada quando a linha roda: um erro de digitação lança um Error ali mesmo. Uma string como 'strtoupr' é só uma string até alguém tentar chamá-la.

Closures dentro de uma classe: $this e static

Uma closure criada dentro de um método tem $this vinculado automaticamente, então pode usar as propriedades do objeto. Marque-a como static function quando ela não precisar de $this, o que também a impede de manter o objeto vivo.

Esquecer o use

O bug de closure mais comum é usar uma variável de fora sem listá-la no use. Dentro da closure a variável não 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 é null lá dentro, qualquer idade comparada com >= null é true, e todas as pessoas passam no filtro. Num servidor que esconde avisos, nada avisa você. Adicione a variável ao use:

Perguntas frequentes

O que é uma closure no PHP?

Uma função sem nome, criada com function (...) { ... } e guardada numa variável ou passada como argumento. O PHP a representa como um objeto da classe Closure. Ela pode levar variáveis do escopo em que foi criada, listadas em use (...).

O que faz a palavra-chave use numa closure PHP?

use ($x) copia a variável de fora $x para dentro da closure quando a closure é criada. Mudanças posteriores em $x lá fora não são vistas. Escreva use (&$x) para compartilhar a variável, para que as mudanças valham nos dois sentidos.

O que é um callable no PHP?

Qualquer coisa que o PHP consegue chamar: uma closure, o nome de uma função como string ('strtoupper'), um array [$object, 'method'] ou [ClassName::class, 'staticMethod'], ou um objeto com __invoke(). Use o tipo callable para aceitar qualquer um deles e is_callable() para verificar.

O que significa strlen(...) no PHP?

É a sintaxe de callable de primeira classe do PHP 8.1: strlen(...) cria uma Closure a partir da função sem chamá-la. Também funciona para métodos, $obj->method(...), e métodos estáticos, Foo::bar(...), e é verificada quando a linha roda, ao contrário de um nome em string.

Preciso de ponto e vírgula depois de uma função anônima?

Sim, quando você a atribui: $f = function () { ... }; é uma instrução de atribuição, então termina com ;. Esquecê-lo é um erro de sintaxe. Uma closure passada direto como argumento não precisa de ponto e vírgula próprio.

Ilustração das linguagens de programação do Coddy

Aprenda a programar com o Coddy

COMEÇAR