Signature
array_walk(array|object &$array, callable $callback, mixed $arg = null): truePurpose
array_walk() visits every element of an array (or the properties of an object) and calls a function of your choosing for each one. It exists for side effects: you either change the values in place or collect information from the elements as you go. It does not build a new array. If you want a transformed copy, array_map() is usually the better fit.
Signature
Parameters and defaults
$arrayis taken by reference, so changes made through the callback show up in your original variable. The walk covers the whole array and ignores the internal array pointer.$callbackis normally called with the element value first and the key second. If the first parameter is declared by reference (&$value), assigning to it changes the element in the array.$argis optional and defaults tonull. When you supply it, it is passed to the callback as a third argument.
Return value and failure cases
The function always returns true. Since PHP 8.2 the declared return type is true; earlier it was bool. Because the result never varies, checking it tells you nothing about whether your callback did what you wanted.
The real failure case is a callback that needs too many arguments. If it requires more than two parameters, or more than three when $arg is passed, PHP throws an ArgumentCountError. Many built-in functions behave the same way when they receive more arguments than they accept, which makes them unsuitable as direct callbacks.
Example 1: changing values with a reference and an extra argument
The callback takes the value by reference and uses the third argument as a multiplier.
$prices = ['apple' => 3, 'pear' => 5];
array_walk($prices, function (&$price, $name, $multiplier) {
$price = $price * $multiplier;
}, 2);
echo json_encode($prices, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"apple":6,"pear":10}
Example 2: collecting data without modifying the array
When the callback only reads, take the value normally. To gather results, capture outside variables by reference with use (&$variable).
$cart = ['a' => 2, 'b' => 3, 'c' => 4];
$total = 0;
$keys = [];
$result = array_walk($cart, function ($qty, $key) use (&$total, &$keys) {
$total += $qty;
$keys[] = strtoupper($key);
});
echo json_encode(['result' => $result, 'total' => $total, 'keys' => $keys], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"result":true,"total":9,"keys":["A","B","C"]}
Example 3: built-in functions as callbacks
Passing 'strtoupper' directly fails because array_walk() also supplies the key, and strtoupper() accepts only one argument. Even if it worked, the function returns a new string rather than altering the element. A small wrapper with a reference parameter solves both problems.
$words = ['red', 'blue'];
try {
array_walk($words, 'strtoupper');
} catch (ArgumentCountError $e) {
echo get_class($e), PHP_EOL;
}
array_walk($words, function (&$word) {
$word = strtoupper($word);
});
echo json_encode($words, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;ArgumentCountError ["RED","BLUE"]
Edge cases
- An empty array is fine: the callback is never called and the function still returns
true. - Only values may be changed. Adding, removing or reordering elements from inside the callback has undefined, unpredictable behavior. Keys cannot be renamed this way.
- The walk is shallow. If an element is itself an array, your callback receives that array as the value. Use
array_walk_recursive()for nested structures. - When you pass an object, the function works on its properties, so visibility rules apply to what the callback can see.
- A callback that declares its second or third parameter by reference triggers an
E_WARNINGsince PHP 8.0. Take the key and$argby value. - The callback may accept fewer than two parameters. Extra values are simply ignored for user-defined functions.
Common mistakes
- Forgetting the
&. Without a by-reference first parameter, the callback changes only a local copy and the array stays the same. - Expecting a return value from the callback to matter. The callback's return value is discarded.
- Using the result of
array_walk()as data. It always returnstrue; the array itself holds the outcome. - Passing a built-in function directly. Functions with strict argument counts raise
ArgumentCountErrorwhen handed the key as well. - Using it when a new array is wanted.
array_map()returns a new array and leaves the source untouched, which is often clearer. Aforeachloop with&$valueis another option, but remember tounsetthe reference afterward. - Altering the array's structure mid-walk. Build a new array separately instead.
Related functions
array_walk_recursive()applies a callback through nested arrays.array_map()returns a transformed copy.iterator_apply()calls a function for each element of an iterator.call_user_func_array()calls a callback with an array of arguments.
Recap
Use array_walk() to run a callback over each element for its side effects. Declare the value parameter by reference to modify elements, pass extra context through $arg or use, keep the callback's parameter count within the limit, and never rely on the return value, which is always true.
Tested examples
$prices = ['apple' => 3, 'pear' => 5];
array_walk($prices, function (&$price, $name, $multiplier) {
$price = $price * $multiplier;
}, 2);
echo json_encode($prices, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"apple":6,"pear":10}
$cart = ['a' => 2, 'b' => 3, 'c' => 4];
$total = 0;
$keys = [];
$result = array_walk($cart, function ($qty, $key) use (&$total, &$keys) {
$total += $qty;
$keys[] = strtoupper($key);
});
echo json_encode(['result' => $result, 'total' => $total, 'keys' => $keys], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"result":true,"total":9,"keys":["A","B","C"]}
$words = ['red', 'blue'];
try {
array_walk($words, 'strtoupper');
} catch (ArgumentCountError $e) {
echo get_class($e), PHP_EOL;
}
array_walk($words, function (&$word) {
$word = strtoupper($word);
});
echo json_encode($words, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;ArgumentCountError ["RED","BLUE"]