array_map(), array_filter() y array_reduce() son las tres funciones de orden superior más usadas en PHP para trabajar con arrays sin bucles explícitos. Transforman, filtran y reducen colecciones de forma declarativa, y con las arrow functions de PHP 7.4 el código resultante es considerablemente más conciso que con los bucles foreach equivalentes.
array_map(): transformar cada elemento
array_map() aplica un callback a cada elemento y devuelve un nuevo array con los resultados. El array original no se modifica:
<?php
$precios = [19.90, 39.90, 89.90, 129.99];
$descuento = 0.20; // 20%
// Con función anónima clásica
$conDescuento = array_map(function($precio) use ($descuento) {
return round($precio * (1 - $descuento), 2);
}, $precios);
// Con arrow function (PHP 7.4+): captura $descuento automáticamente
$conDescuento = array_map(fn($p) => round($p * (1 - $descuento), 2), $precios);
print_r($conDescuento);
// Array ( [0] => 15.92 [1] => 31.92 [2] => 71.92 [3] => 103.99 )
?>
array_filter(): seleccionar elementos
array_filter() devuelve los elementos para los que el callback devuelve true. Sin callback, elimina los valores falsy (false, 0, '', null):
<?php
$emails = [
'[email protected]',
'invalido',
'[email protected]',
'',
'[email protected]',
];
// Filtrar solo los emails válidos
$validos = array_filter($emails, fn($e) => filter_var($e, FILTER_VALIDATE_EMAIL) !== false);
print_r(array_values($validos)); // reindexar las claves
// Array ( [0] => [email protected] [1] => [email protected] [2] => [email protected] )
?>
Nota: array_filter() preserva las claves originales. Si necesitas un array reindexado desde 0, usa array_values() después.
array_reduce(): acumular un resultado único
array_reduce() aplica un callback acumulador para reducir el array a un valor único. El tercer argumento es el valor inicial:
<?php
$carrito = [
['nombre' => 'Camiseta', 'precio' => 19.90, 'cantidad' => 2],
['nombre' => 'Pantalón', 'precio' => 39.90, 'cantidad' => 1],
['nombre' => 'Zapatillas', 'precio' => 89.90, 'cantidad' => 1],
];
$total = array_reduce($carrito, function(float $acum, array $item): float {
return $acum + ($item['precio'] * $item['cantidad']);
}, 0.0);
echo number_format($total, 2, ',', '.') . ' ';
// 169,60
?>
Pipeline de transformaciones con arrays
Encadenar las tres funciones da lugar a un flujo de datos claro y sin variables temporales:
<?php
$ficheros = [
'logo.png',
'script.js',
'imagen-producto-1.jpg',
'styles.css',
'imagen-hero.webp',
'thumbnail.png',
];
$extensionesImagen = ['jpg', 'jpeg', 'png', 'webp', 'gif'];
// 1. Filtrar solo imágenes
// 2. Obtener el nombre sin extensión
// 3. Construir URL pública
$urlsImagenes = array_map(
fn($f) => '/uploads/' . pathinfo($f, PATHINFO_FILENAME),
array_filter(
$ficheros,
fn($f) => in_array(strtolower(pathinfo($f, PATHINFO_EXTENSION)), $extensionesImagen)
)
);
print_r(array_values($urlsImagenes));
// Array ( [0] => /uploads/logo [1] => /uploads/imagen-producto-1 ... )
?>
Cuándo seguir usando foreach
array_map/filter/reduce brillan cuando la transformación es una expresión pura (sin efectos secundarios). Si dentro del callback necesitas escribir en base de datos, lanzar excepciones condicionalmente o mantener estado entre iteraciones, un foreach explícito es más claro y más fácil de depurar.
La documentación oficial de array_map() explica también el comportamiento especial cuando se le pasan múltiples arrays como argumento.
