array_walk y array_walk_recursive en PHP: modificar arrays en profundidad

array_walk() aplica un callback a cada elemento de un array pasándolo por referencia. La diferencia clave respecto a array_map() es que array_walk() modifica el array original en lugar de devolver uno nuevo, y el callback recibe tanto el valor como la clave. array_walk_recursive() hace lo mismo pero desciende a todos los niveles de arrays anidados.

Sintaxis

<?php
array_walk(array|object &$array, callable $callback, mixed $arg = null): bool
array_walk_recursive(array|object &$array, callable $callback, mixed $arg = null): bool
?>

El callback recibe el valor por referencia (si lo declaras con &), la clave y opcionalmente el tercer argumento de array_walk():

<?php
$nombres = ['ana', 'carlos', 'MARTA', 'luís'];

// Normalizar a Title Case: modifica el array original
array_walk($nombres, function(&$nombre) {
    $nombre = mb_convert_case(trim($nombre), MB_CASE_TITLE, 'UTF-8');
});

print_r($nombres);
// Array ( [0] => Ana [1] => Carlos [2] => Marta [3] => Luís )
?>

El callback también recibe la clave

<?php
$precios = ['camiseta' => 19.90, 'pantalon' => 39.90, 'zapatillas' => 89.90];

array_walk($precios, function(&$precio, $producto) {
    echo "$producto: " . number_format($precio, 2, ',', '.') . " €n";
    $precio = round($precio * 1.21, 2); // aplicar IVA
});

// camiseta: 19,90 €
// pantalon: 39,90 €
// zapatillas: 89,90 €

print_r($precios);
// Array ( [camiseta] => 24.08 [pantalon] => 48.28 [zapatillas] => 108.78 )
?>

El tercer argumento como datos adicionales

<?php
$descripciones = [
    'intro'  => 'Aprende PHP desde cero',
    'avanzado' => 'Traits, generadores y fibers',
    'testing'  => 'PHPUnit y test doubles',
];

// Pasar el prefijo como dato extra
array_walk($descripciones, function(&$desc, $clave, $prefijo) {
    $desc = "[$prefijo] $desc";
}, 'CURSO');

print_r($descripciones);
// Array ( [intro] => [CURSO] Aprende PHP desde cero ... )
?>

array_walk_recursive(): modificar arrays anidados

<?php
$catalogo = [
    'ropa' => [
        'camiseta' => '  Camiseta básica  ',
        'pantalon' => "t Pantalón chino n",
    ],
    'calzado' => [
        'zapatillas' => ' Zapatillas running ',
    ],
];

// Limpiar espacios en todos los niveles
array_walk_recursive($catalogo, function(&$valor) {
    if (is_string($valor)) {
        $valor = trim($valor);
    }
});

print_r($catalogo);
// Array ( [ropa] => Array ( [camiseta] => Camiseta básica [pantalon] => Pantalón chino ) [calzado] => ... )
?>

Diferencias clave con array_map()

  • array_map() devuelve un nuevo array; array_walk() modifica el original
  • array_walk() pasa la clave al callback; array_map() no (a menos que uses array_keys() explícitamente)
  • array_walk() permite pasar datos extra al callback mediante el tercer argumento
  • array_walk_recursive() desciende a todos los niveles; array_map() es solo un nivel
<?php
// array_map: más idiomático cuando quieres el resultado sin modificar el original
$preciosConIva = array_map(fn($p) => round($p * 1.21, 2), $precios);

// array_walk: cuando necesitas la clave o modificar el original en su lugar
array_walk($precios, fn(&$p, $nombre) => ($p = round($p * 1.21, 2)));
?>

La documentación oficial de array_walk() y la de array_walk_recursive() explican el comportamiento con objetos y los cambios entre versiones.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP