Arrow Functions
1. Introdução às Arrow Functions
Arrow functions representam uma das adições mais elegantes ao PHP moderno. Introduzidas no PHP 7.4, elas oferecem uma sintaxe concisa para escrever funções anônimas de uma única expressão. A estrutura básica é fn($x) => $x * 2, que substitui closures tradicionais mais verbosas.
Antes das arrow functions, um closure simples para dobrar um número exigia:
$dobrar = function($x) {
return $x * 2;
};
Com arrow functions, o mesmo código se reduz a:
$dobrar = fn($x) => $x * 2;
A diferença visual é marcante: menos cerimônia, mais foco na lógica essencial.
2. Sintaxe Básica
A estrutura mínima de uma arrow function segue o padrão fn(argumentos) => expressão. O retorno é implícito — não há necessidade de return.
// Sintaxe básica
$quadrado = fn($n) => $n * $n;
echo $quadrado(5); // 25
// Múltiplos parâmetros
$soma = fn($a, $b) => $a + $b;
echo $soma(3, 7); // 10
Parâmetros tipados e valores padrão funcionam normalmente:
// Com type hinting
$calcular = fn(int $a, int $b): int => $a + $b;
// Valores padrão
$saudacao = fn(string $nome = 'Mundo') => "Olá, $nome!";
echo $saudacao(); // Olá, Mundo!
echo $saudacao('Maria'); // Olá, Maria!
3. Captura de Variáveis do Escopo Pai
Uma das vantagens mais significativas das arrow functions é a captura automática de variáveis do escopo pai. Diferente das closures tradicionais, que exigem use explícito, as arrow functions capturam variáveis automaticamente por valor.
$fator = 3;
$numeros = [1, 2, 3, 4, 5];
// Closure tradicional — requer 'use'
$multiplicarTradicional = array_map(function($n) use ($fator) {
return $n * $fator;
}, $numeros);
// Arrow function — captura automática
$multiplicarArrow = array_map(fn($n) => $n * $fator, $numeros);
print_r($multiplicarArrow); // [3, 6, 9, 12, 15]
A captura inclui $this automaticamente em contextos de objeto:
class Conversor {
private float $taxa = 1.25;
public function converter(array $valores): array {
// $this está disponível automaticamente
return array_map(fn($v) => $v * $this->taxa, $valores);
}
}
$conv = new Conversor();
print_r($conv->converter([100, 200])); // [125, 250]
4. Limitações Importantes
Arrow functions têm restrições claras que é essencial conhecer:
Apenas uma expressão: não é possível usar chaves {} ou múltiplas instruções.
// Inválido — não compile
$invalido = fn($x) => {
$y = $x * 2;
return $y + 1;
};
// Correto — deve ser expressão única
$valido = fn($x) => ($x * 2) + 1;
Sem suporte a declarações: estruturas como if, for, while não são permitidas.
// Inválido
$parOuImpar = fn($n) => if ($n % 2 === 0) 'par' else 'impar';
// Alternativa com operador ternário
$parOuImpar = fn($n) => ($n % 2 === 0) ? 'par' : 'impar';
Sem referências explícitas: não é possível usar & para capturar por referência.
$contador = 0;
// Não funciona como esperado — arrow function captura por valor
$incrementar = fn() => $contador++;
$incrementar(); // $contador continua 0
// Closure tradicional com referência
$incrementarRef = function() use (&$contador) {
$contador++;
};
$incrementarRef(); // $contador agora é 1
5. Uso com Funções de Array
Arrow functions brilham especialmente com funções de manipulação de arrays, reduzindo drasticamente a verbosidade do código.
array_map — transformação concisa:
$numeros = [1, 2, 3, 4, 5];
// Closure tradicional
$aoQuadradoTrad = array_map(function($n) {
return $n ** 2;
}, $numeros);
// Arrow function
$aoQuadradoArrow = array_map(fn($n) => $n ** 2, $numeros);
print_r($aoQuadradoArrow); // [1, 4, 9, 16, 25]
array_filter — filtragem simplificada:
$idades = [12, 18, 25, 30, 15, 22];
// Filtrar maiores de idade com variável externa
$idadeMinima = 18;
$maiores = array_filter($idades, fn($idade) => $idade >= $idadeMinima);
print_r($maiores); // [18, 25, 30, 22]
array_reduce — redução elegante:
$valores = [10, 20, 30, 40];
// Soma com arrow function
$soma = array_reduce($valores, fn($carry, $item) => $carry + $item, 0);
echo $soma; // 100
6. Arrow Functions Aninhadas e Callbacks
Arrow functions podem ser aninhadas e usadas como callbacks em contextos mais complexos:
// Arrow function que retorna outra arrow function
$multiplicador = fn($fator) => fn($valor) => $valor * $fator;
$dobro = $multiplicador(2);
$triplo = $multiplicador(3);
echo $dobro(5); // 10
echo $triplo(5); // 15
Uso em pipelines de processamento:
$processar = fn($arr) =>
array_map(fn($n) => $n * 2,
array_filter($arr, fn($n) => $n > 0)
);
$dados = [-1, 2, -3, 4, 5];
print_r($processar($dados)); // [4, 8, 10]
Armadilha comum de escopo aninhado:
$valores = [1, 2, 3];
// Cuidado: cada arrow function captura seu próprio escopo
$resultados = array_map(
fn($x) => array_map(
fn($y) => $x * $y, // $x vem do escopo externo
[10, 20]
),
$valores
);
print_r($resultados); // [[10, 20], [20, 40], [30, 60]]
7. Performance e Boas Práticas
Arrow functions oferecem vantagens de performance por terem menos overhead que closures tradicionais — não há necessidade de criar um escopo de variáveis separado com use.
Quando usar arrow functions:
- Operações simples de transformação em arrays
- Callbacks curtos em funções como array_map, array_filter
- Expressões matemáticas ou lógicas diretas
- Contextos onde a captura automática de variáveis é desejada
Quando preferir closures tradicionais:
- Lógica com múltiplas instruções ou estruturas de controle
- Necessidade de capturar variáveis por referência
- Operações que exigem modificação de estado externo
- Código que precisa de documentação inline mais detalhada
Exemplo de boa prática:
// Bom uso de arrow function
$precosComTaxa = array_map(
fn($preco) => $preco * (1 + $taxa),
$precos
);
// Caso que justifica closure tradicional
$processarPedido = function($pedido) use (&$estoque, $taxa) {
if ($estoque[$pedido['item']] < $pedido['quantidade']) {
throw new \Exception('Estoque insuficiente');
}
$estoque[$pedido['item']] -= $pedido['quantidade'];
return $pedido['preco'] * $pedido['quantidade'] * (1 + $taxa);
};
8. Casos Avançados e Curiosidades
Tipos de retorno declarados:
// Declaração explícita de tipo de retorno
$calcular = fn(int $a, int $b): int => $a + $b;
Uso com match expressions (PHP 8.0+):
$classificar = fn($nota) => match(true) {
$nota >= 9 => 'Excelente',
$nota >= 7 => 'Bom',
$nota >= 5 => 'Regular',
default => 'Insuficiente'
};
echo $classificar(8.5); // Bom
Arrow functions em métodos e traits:
trait OperacoesMatematicas {
public function aplicarOperacao(array $valores): array {
return array_map(fn($v) => $this->operacao($v), $valores);
}
abstract protected function operacao($valor);
}
class Calculadora {
use OperacoesMatematicas;
protected function operacao($valor) {
return $valor ** 2;
}
}
$calc = new Calculadora();
print_r($calc->aplicarOperacao([1, 2, 3])); // [1, 4, 9]
Arrow functions com variáveis de instância:
class Filtro {
private int $limite = 10;
public function filtrar(array $dados): array {
// Captura automática de $this
return array_filter($dados, fn($item) => $item > $this->limite);
}
}
Arrow functions representam um avanço significativo na expressividade do PHP, permitindo código mais limpo e funcional. Dominá-las é essencial para qualquer desenvolvedor PHP moderno que busca escrever código elegante e eficiente.
Referências
- PHP Manual: Arrow Functions — Documentação oficial completa sobre arrow functions no PHP, incluindo sintaxe, exemplos e limitações.
- PHP 7.4 Release Announcement — Anúncio oficial do PHP 7.4 com detalhes sobre a introdução das arrow functions.
- Stitcher.io: Arrow Functions in PHP — Artigo técnico detalhado com exemplos práticos e comparações entre closures e arrow functions.
- PHP.Watch: Arrow Functions — Guia completo sobre arrow functions no PHP 7.4, incluindo mudanças de comportamento e boas práticas.
- Laravel News: PHP Arrow Functions — Tutorial prático com exemplos de uso de arrow functions em cenários reais de desenvolvimento.
- PHP The Right Way: Arrow Functions — Seção do guia "PHP The Right Way" abordando arrow functions no contexto de programação funcional.