array_map($callback, $array) llama a $callback con cada elemento de $array y devuelve un array nuevo con los resultados. Primero va el callback y después el array, y el array original no se modifica.
fn($p) => $p * 1.2 es una función flecha: una función de una sola expresión que devuelve su resultado. En su lugar sirve cualquier callable.
Usar una función nativa como callback
Pasa el nombre de una función nativa como cadena. Es la forma más corta de limpiar un array entero: recortar cada valor, convertir cadenas en enteros o cambiar mayúsculas y minúsculas.
array_map('intval', ...) es la forma habitual de convertir en enteros de verdad las cadenas que llegan de un formulario o de explode(). También puedes escribir intval(...), la sintaxis de callable de primera clase de PHP 8.1, que tu editor puede autocompletar y comprobar.
Usar un closure con variables de fuera
Una función flecha ve automáticamente las variables que la rodean. Una function clásica necesita use para traerlas. Las dos se explican en la página de funciones anónimas.
array_map con claves
Con un solo array, array_map conserva las claves, incluidas las de texto. Pero el callback solo recibe el valor. Para obtener también la clave, pasa array_keys($array) como segundo array: el callback se llama entonces con un elemento de cada array.
Fíjate en el segundo resultado: en cuanto pasas más de un array, las claves se sustituyen por 0, 1, 2. Por eso la última línea usa array_combine() para reconstruirlas.
Mapear varios arrays a la vez
Cada array extra se convierte en un argumento extra del callback, emparejado por posición. Si los arrays tienen longitudes distintas, los más cortos se rellenan con null.
Pasar null como callback se salta la función y empareja los arrays en parejas:
array_map vs array_walk vs foreach
array_map construye un array nuevo. array_walk cambia el array que le pasas, mediante una referencia, y le da al callback la clave como segundo argumento. Un foreach hace cualquiera de las dos cosas y además puede saltarse elementos o parar antes con break.
Usa array_map cuando cada elemento se convierte exactamente en un elemento nuevo. Si además necesitas descartar algunos elementos, combínalo con array_filter, o escribe un foreach.
Error frecuente: el orden de los argumentos
array_map recibe primero el callback y después el array. Su vecina array_filter los recibe al revés, y es fácil confundirlas:
array_map($callback, $array); // callback first
array_filter($array, $callback); // array first
Si los intercambias, PHP 8 lanza un TypeError, porque un array normal no es un callback válido:
PHP se detiene con:
PHP Fatal error: Uncaught TypeError: array_map(): Argument #1 ($callback) must be a valid callback or null, array callback must have exactly two members in /home/index.php:4
Vuelve a poner los dos argumentos en su orden y el bloque funciona.
Preguntas frecuentes
¿Qué hace array_map en PHP?
Llama a una función con cada elemento de un array y devuelve un array nuevo con los resultados: array_map(fn($n) => $n * 2, [1, 2, 3]) devuelve [2, 4, 6]. El array original no cambia.
¿array_map conserva las claves?
Con un solo array, sí: las claves de texto y enteras se mantienen tal cual. Con dos o más arrays, el resultado siempre recibe claves nuevas 0, 1, 2....
¿Cómo obtengo la clave dentro del callback de array_map?
Pasa las claves como segundo array: array_map(fn($k, $v) => "$k=$v", array_keys($arr), $arr). El resultado es una lista, así que envuélvelo en array_combine(array_keys($arr), ...) si necesitas recuperar las claves originales.
¿array_map es más rápido que foreach?
No de forma apreciable. Los dos recorren el array una vez, y un foreach simple suele ser algo más rápido porque evita una llamada a función por elemento. Elige array_map cuando se lea mejor: una transformación que produce un array nuevo.
¿Cuál es la diferencia entre array_map y array_walk?
array_map devuelve un array nuevo y no toca la entrada. array_walk devuelve true y está pensado para cambiar el array en el sitio mediante un parámetro por referencia: array_walk($arr, function (&$v, $k) { $v = trim($v); });.