Arrow Functions
Las arrow functions (funciones flecha),
introducidas en PHP 7.4, son una sintaxis mas
concisa para escribir funciones anonimas de una
sola expresion. Capturan automaticamente las
variables del ambito exterior sin necesidad de
usar use.
Sintaxis basica
Las arrow functions usan la palabra clave
fn seguida de los parametros, una
flecha => y una expresion:
<?php
declare(strict_types=1);
// Funcion anonima tradicional
$sumarTradicional = function (int $a, int $b): int {
return $a + $b;
};
// Arrow function equivalente
$sumar = fn (int $a, int $b): int => $a + $b;
echo $sumar(5, 3); // 8
// Mas ejemplos
$duplicar = fn (int $n): int => $n * 2;
$esPar = fn (int $n): bool => $n % 2 === 0;
$saludar = fn (string $nombre): string => "Hola, $nombre";
echo $duplicar(7); // 14
var_dump($esPar(4)); // true
echo $saludar('Maria'); // Hola, Maria
Las arrow functions solo pueden contener una expresion. No puedes usar multiples sentencias ni bloques de codigo. El resultado de la expresion se retorna automaticamente.
Captura automatica de variables
A diferencia de las funciones anonimas tradicionales, las arrow functions capturan automaticamente las variables del ambito exterior por valor:
<?php
declare(strict_types=1);
$multiplicador = 10;
// Funcion anonima: necesita use
$multiplicarTradicional = function (int $n) use ($multiplicador): int {
return $n * $multiplicador;
};
// Arrow function: captura automatica
$multiplicar = fn (int $n): int => $n * $multiplicador;
echo $multiplicar(5); // 50
// Captura de multiples variables
$base = 100;
$descuento = 0.15;
$calcularPrecio = fn (float $precio): float => $base + $precio - ($precio * $descuento);
echo $calcularPrecio(50); // 142.5 (100 + 50 - 7.5)
Comparacion con funciones anonimas
Las arrow functions son ideales para transformaciones simples donde la sintaxis tradicional seria verbosa:
<?php
declare(strict_types=1);
$numeros = [1, 2, 3, 4, 5];
$factor = 3;
// Funcion anonima tradicional (verbosa)
$cubosTradicional = array_map(function (int $n): int {
return $n ** 3;
}, $numeros);
// Arrow function (concisa)
$cubos = array_map(fn (int $n): int => $n ** 3, $numeros);
print_r($cubos); // [1, 8, 27, 64, 125]
// Con captura de variable
// Tradicional
$multiplicadosTradicional = array_map(function (int $n) use ($factor): int {
return $n * $factor;
}, $numeros);
// Arrow function
$multiplicados = array_map(fn (int $n): int => $n * $factor, $numeros);
print_r($multiplicados); // [3, 6, 9, 12, 15]
Uso con funciones de arrays
Las arrow functions brillan especialmente con
funciones como
array_map,
array_filter y usort:
<?php
declare(strict_types=1);
$productos = [
['nombre' => 'Laptop', 'precio' => 999.99],
['nombre' => 'Mouse', 'precio' => 29.99],
['nombre' => 'Teclado', 'precio' => 79.99],
['nombre' => 'Monitor', 'precio' => 349.99],
];
// Extraer solo los nombres
$nombres = array_map(fn (array $p): string => $p['nombre'], $productos);
print_r($nombres); // ['Laptop', 'Mouse', 'Teclado', 'Monitor']
// Extraer solo los precios
$precios = array_map(fn (array $p): float => $p['precio'], $productos);
print_r($precios); // [999.99, 29.99, 79.99, 349.99]
// Filtrar productos caros (mas de 100)
$caros = array_filter($productos, fn (array $p): bool => $p['precio'] > 100);
print_r($caros);
// [['nombre' => 'Laptop', ...], ['nombre' => 'Monitor', ...]]
// Aplicar descuento del 10%
$descuento = 0.10;
$conDescuento = array_map(
fn (array $p): array => [
'nombre' => $p['nombre'],
'precio' => $p['precio'] * (1 - $descuento),
],
$productos
);
print_r($conDescuento);
Ordenamiento con arrow functions
<?php
declare(strict_types=1);
$usuarios = [
['nombre' => 'Ana', 'edad' => 28],
['nombre' => 'Luis', 'edad' => 35],
['nombre' => 'Eva', 'edad' => 22],
['nombre' => 'Carlos', 'edad' => 30],
];
// Ordenar por edad (ascendente)
usort($usuarios, fn (array $a, array $b): int => $a['edad'] <=> $b['edad']);
// Eva(22), Ana(28), Carlos(30), Luis(35)
// Ordenar por edad (descendente)
usort($usuarios, fn (array $a, array $b): int => $b['edad'] <=> $a['edad']);
// Luis(35), Carlos(30), Ana(28), Eva(22)
// Ordenar por nombre
usort($usuarios, fn (array $a, array $b): int => $a['nombre'] <=> $b['nombre']);
// Ana, Carlos, Eva, Luis
$palabras = ['banana', 'Manzana', 'cereza', 'Uva'];
// Ordenar sin distinguir mayusculas/minusculas
usort($palabras, fn (string $a, string $b): int => strcasecmp($a, $b));
print_r($palabras); // ['banana', 'cereza', 'Manzana', 'Uva']
Encadenamiento de operaciones
Las arrow functions permiten crear cadenas de transformaciones legibles:
<?php
declare(strict_types=1);
$numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Obtener la suma de los cuadrados de los numeros pares
$resultado = array_sum(
array_map(
fn (int $n): int => $n ** 2,
array_filter($numeros, fn (int $n): bool => $n % 2 === 0)
)
);
echo $resultado; // 220 (4 + 16 + 36 + 64 + 100)
// Procesar pedidos
$pedidos = [
['producto' => 'A', 'cantidad' => 3, 'precio' => 10.00],
['producto' => 'B', 'cantidad' => 1, 'precio' => 25.00],
['producto' => 'C', 'cantidad' => 5, 'precio' => 5.00],
['producto' => 'D', 'cantidad' => 2, 'precio' => 15.00],
];
$impuesto = 0.21;
// Calcular totales con impuesto para pedidos mayores a 20
$totalesConImpuesto = array_map(
fn (array $p): float => $p['cantidad'] * $p['precio'] * (1 + $impuesto),
array_filter(
$pedidos,
fn (array $p): bool => $p['cantidad'] * $p['precio'] > 20
)
);
print_r($totalesConImpuesto);
// [36.30 (producto A), 30.25 (producto B), 30.25 (producto C), 36.30 (producto D)]
Arrow functions anidadas
Puedes retornar arrow functions desde otras arrow functions:
<?php
declare(strict_types=1);
// Fabrica de multiplicadores
$crearMultiplicador = fn (int $factor): callable => fn (int $n): int => $n * $factor;
$duplicar = $crearMultiplicador(2);
$triplicar = $crearMultiplicador(3);
$porCien = $crearMultiplicador(100);
echo $duplicar(5); // 10
echo $triplicar(5); // 15
echo $porCien(5); // 500
// Fabrica de comparadores
$crearComparador = fn (string $campo): callable =>
fn (array $a, array $b): int => $a[$campo] <=> $b[$campo];
$usuarios = [
['nombre' => 'Ana', 'puntos' => 150],
['nombre' => 'Luis', 'puntos' => 200],
['nombre' => 'Eva', 'puntos' => 100],
];
// Ordenar por puntos
usort($usuarios, $crearComparador('puntos'));
print_r($usuarios);
// Eva(100), Ana(150), Luis(200)
// Ordenar por nombre
usort($usuarios, $crearComparador('nombre'));
print_r($usuarios);
// Ana, Eva, Luis
Limitaciones de las arrow functions
Es importante conocer cuando no usar arrow functions:
<?php
declare(strict_types=1);
// NO PUEDES: usar multiples lineas
// fn (int $n): int => {
// $resultado = $n * 2;
// return $resultado;
// };
// SI PUEDES: usar funcion anonima para logica compleja
$procesarComplejo = function (array $datos): array {
$resultado = [];
foreach ($datos as $item) {
if ($item > 0) {
$resultado[] = $item * 2;
}
}
return $resultado;
};
// NO PUEDES: capturar por referencia
$contador = 0;
// fn (): int => ++$contador; // No modifica el original
// SI PUEDES: usar funcion anonima con &
$incrementar = function () use (&$contador): int {
return ++$contador;
};
echo $incrementar(); // 1
echo $incrementar(); // 2
echo $contador; // 2
// NO PUEDES: usar sentencias (solo expresiones)
// fn (): void => echo 'hola'; // Error: echo es una sentencia
// SI PUEDES: retornar el resultado de una expresion
$obtenerMensaje = fn (): string => 'hola';
Usa arrow functions para transformaciones simples de una linea. Usa funciones anonimas tradicionales cuando necesites multiples sentencias, captura por referencia, o logica compleja.
Ejemplo practico: Validador de datos
<?php
declare(strict_types=1);
// Definir validadores como arrow functions
$esRequerido = fn (mixed $valor): bool => $valor !== null && $valor !== '';
$esEmail = fn (string $valor): bool => filter_var($valor, FILTER_VALIDATE_EMAIL) !== false;
$longitudMinima = fn (int $min): callable => fn (string $valor): bool => strlen($valor) >= $min;
$longitudMaxima = fn (int $max): callable => fn (string $valor): bool => strlen($valor) <= $max;
$esNumerico = fn (mixed $valor): bool => is_numeric($valor);
$entreValores = fn (int $min, int $max): callable =>
fn (int $valor): bool => $valor >= $min && $valor <= $max;
// Funcion para validar un campo con multiples reglas
function validarCampo(mixed $valor, array $reglas): array
{
$errores = [];
foreach ($reglas as $nombre => $regla) {
if (!$regla($valor)) {
$errores[] = $nombre;
}
}
return $errores;
}
// Validar un email
$email = 'usuario@example.com';
$erroresEmail = validarCampo($email, [
'requerido' => $esRequerido,
'formato_email' => $esEmail,
'longitud_minima' => $longitudMinima(5),
'longitud_maxima' => $longitudMaxima(100),
]);
if (empty($erroresEmail)) {
echo "Email valido\n";
} else {
echo 'Errores: ' . implode(', ', $erroresEmail) . "\n";
}
// Validar edad
$edad = 25;
$erroresEdad = validarCampo($edad, [
'requerido' => $esRequerido,
'numerico' => $esNumerico,
'rango_valido' => $entreValores(18, 120),
]);
var_dump(empty($erroresEdad)); // true
Ejemplo practico: Transformacion de datos
<?php
declare(strict_types=1);
// Datos de usuarios de una API
$usuariosApi = [
['id' => 1, 'first_name' => 'ana', 'last_name' => 'garcia', 'active' => 1],
['id' => 2, 'first_name' => 'luis', 'last_name' => 'perez', 'active' => 0],
['id' => 3, 'first_name' => 'eva', 'last_name' => 'lopez', 'active' => 1],
];
// Transformadores
$capitalizar = fn (string $texto): string => ucfirst(strtolower($texto));
$nombreCompleto = fn (array $u): string => $capitalizar($u['first_name']) . ' ' . $capitalizar($u['last_name']);
$esActivo = fn (array $u): bool => $u['active'] === 1;
// Transformar datos
$usuariosActivos = array_filter($usuariosApi, $esActivo);
$nombres = array_map($nombreCompleto, $usuariosActivos);
print_r($nombres); // ['Ana Garcia', 'Eva Lopez']
// Crear estructura para la vista
$usuariosVista = array_map(
fn (array $u): array => [
'id' => $u['id'],
'nombre' => $nombreCompleto($u),
'estado' => $esActivo($u) ? 'Activo' : 'Inactivo',
],
$usuariosApi
);
print_r($usuariosVista);
/*
[
['id' => 1, 'nombre' => 'Ana Garcia', 'estado' => 'Activo'],
['id' => 2, 'nombre' => 'Luis Perez', 'estado' => 'Inactivo'],
['id' => 3, 'nombre' => 'Eva Lopez', 'estado' => 'Activo'],
]
*/
Ejercicios
Ejercicio 1: Arrow function basica
Convierte esta funcion anonima a arrow
function:
$cuadrado = function (int $n): int
{ return $n * $n; };
Ver solucion
<?php
declare(strict_types=1);
$cuadrado = fn (int $n): int => $n * $n;
echo $cuadrado(5); // 25
echo $cuadrado(12); // 144
Ejercicio 2: Captura automatica de variables
Tienes una variable
$descuento = 0.15. Crea una
arrow function
$aplicarDescuento que
reciba un precio y retorne el precio con
el descuento aplicado. Recuerda que las
arrow functions capturan variables
automaticamente.
Ver solucion
<?php
declare(strict_types=1);
$descuento = 0.15;
$aplicarDescuento = fn (float $precio): float => $precio * (1 - $descuento);
echo $aplicarDescuento(100.0); // 85.0
echo $aplicarDescuento(50.0); // 42.5
Ejercicio 3: Transformar array con arrow function
Usa array_map con una arrow
function para convertir un array de
temperaturas en Celsius a Fahrenheit.
Formula: F = C * 9/5 + 32. Array de
entrada: [0, 20, 100].
Ver solucion
<?php
declare(strict_types=1);
$celsius = [0, 20, 100];
$fahrenheit = array_map(
fn (int $c): float => $c * 9 / 5 + 32,
$celsius
);
print_r($fahrenheit);
// [32.0, 68.0, 212.0]
¿Has encontrado un error o tienes una sugerencia para mejorar esta leccion?
Escribenos¿Te está gustando el curso?
Tenemos cursos premium con proyectos reales y soporte personalizado.
Descubrir cursos premium