Complete Guide to PHP's array_walk_recursive() Function
Learn PHP's array_walk_recursive(): apply a callback to every leaf in nested arrays, modify values by reference, with examples and gotchas.
array_walk_recursive() applies a callback to every non-array value (leaf) in an array, descending into nested arrays automatically. Unlike a manual foreach, you don't have to write the recursion yourself, and unlike array_map(), it can modify the original array in place by taking each value by reference.
This chapter covers the function signature, how it walks nested arrays, modifying values by reference, the role of the optional third argument, and the gotchas that trip people up (objects, keys, and what counts as a "leaf").
Syntax
array_walk_recursive(array|object &$array, callable $callback, mixed $arg = null): true$array— the array to walk. It is passed by reference, so the callback can change its contents.$callback— a callable invoked once per leaf, receiving($value, $key). Declare$valueas&$valueto edit the array in place.$arg— an optional extra argument passed (by value) to the callback as its third parameter.
The function returns true. Only leaf values reach the callback — keys that hold sub-arrays are descended into but never passed to it.
How it walks nested arrays
The callback fires for each scalar element, and whenever an element is itself an array, array_walk_recursive() walks into that array too. The next example prints each key: value pair, including the ones inside the nested array:
Output:
0: a
1: b
0: c
1: d
2: e
3: fNote that the nested array itself (the one holding c, d, e) is not passed to the callback — only its leaves are. The keys you receive are the keys within each level, which is why c, d, e report 0, 1, 2 again.
Modifying values by reference
The most common real use of this function is transforming an entire nested structure in place. Take the value &$value by reference and assign to it. Here every price gets a 10% tax added, no matter how deeply it is nested:
<?php
$prices = [
'fruit' => ['apple' => 1.00, 'pear' => 2.00],
'drinks' => ['water' => 0.50],
];
array_walk_recursive($prices, function (&$value, $key) {
$value = round($value * 1.10, 2); // add 10% tax
});
print_r($prices);
?>Output:
Array
(
[fruit] => Array
(
[apple] => 1.1
[pear] => 2.2
)
[drinks] => Array
(
[water] => 0.55
)
)Passing extra data with the third argument
The optional $arg is handed to the callback (by value) as a third parameter — handy for passing configuration without a closure. Here a prefix string is supplied once and reused for every leaf:
<?php
$data = ['name' => 'ada', 'team' => ['bob', 'cara']];
array_walk_recursive($data, function ($value, $key, $prefix) {
echo $prefix . ucfirst($value) . "\n";
}, ">> ");
?>Output:
>> Ada
>> Bob
>> CaraBecause $arg is passed by value, you cannot use it to accumulate results across calls. To build up a value, capture a variable by reference with use (&$total) instead:
<?php
$data = [1, [2, 3], 4];
$sum = 0;
array_walk_recursive($data, function ($value, $key) use (&$sum) {
$sum += $value;
});
echo "Sum: $sum\n"; // Sum: 10
?>Gotchas
- Only arrays are recursed into. A leaf is anything that isn't an array — including objects. An
stdClassinside your data is passed to the callback as a single value, not walked into. - The nested array nodes never reach the callback. If you need to act on container arrays themselves (not just leaves), use
array_walk()or a manual recursiveforeach. - Modifying requires
&$value. Without the reference, assignments inside the callback are discarded and the original array is unchanged. - Keys can repeat across levels. The
$keyyou get is the key at its own level, so the same key value can show up in different branches.
Related functions
array_walk()— same idea, but only one level deep.array_map()— returns a new array instead of mutating in place.array_filter()— keep elements that pass a test.- PHP Arrays — array basics and other helpers.