Use array_walk
instead of foreach
A developer wants to itterate over an array or itterable object.
The developer decides to use foreach
.
foreach
executes code set in the body of the foreach
for each element of a given array.
Any variable set in the body of the foreach
will still be available after the foreach
.
<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
$value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
unset($value); // break the reference with the last element
By using array_walk()
, the code becomes more explicit:
- Any variable outside the
foreach
can be accessed withing theforeach
body. Witharray_walk()
this is not the case. Variables need to be passed in (either withuse
or as a third parameter toarray_walk()
) any changes to such variable does not exist beyond thefunction
. If changes need to persist, a variable needs to be passed by reference (using&
) - Any variable outside the
foreach
can be changed withing theforeach
body. Witharray_walk()
this is not the case. Even if variables are passed in (see code example withuse
) any changes to such variable does not exist beyond thefunction
. If changes need to persist, a variable needs to be passed by reference (using&
)
Use array_walk
<?php
array_walk ($array, function ($value){
list($a, $b) = $value;
// $a contains the first element of the nested array,
// and $b contains the second element.
echo "A: $a; B: $b\n";
});
- Code should be explicit
- Do not cause side-effects
- Encapsulation / Scope restaint
- Re-usability
<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
$value = $value * 2;
}
var_dump($arr); // array(2, 4, 6, 8)
unset($value); // break the reference with the last element
$arr = array(1, 2, 3, 4);
array_walk($arr, function (&$value) {
$value = $value * 2;
});
var_dump($arr); // array(2, 4, 6, 8)
// no reference with last element is present
/* 1. "Normal" itteration with an action */
foreach ($a as $b => $c) {
// do a thing with $b and/or $c
}
/* 2. Moving the action out of the itteration */
function do_a_thing($b, $c) {
// do a thing with $b and/or $c
}
foreach ($a as $b => $c) {
do_a_thing($b, $c);
}
/* 3. Replacing the `foreach` with an `array_walk` to reduce code */
function do_a_thing($b, $c) {
// do a thing with $b and/or $c
}
array_walk($a, 'do_a_thing');
/* 4. Moving the action into `array_walk` for readability */
array_walk($a, function ($b, $c) {
// do a thing with $b and/or $c
});
Lately I find myself use array_walk
a lot more often than foreach
.
This may be because I'm being drawn deeper and deeper into the rabithole called functional programming but there are some other reasons I would like to explain.
I am sure any developer who has ever worked with PHP is (at least vaguely) familiar with foreach
. This might not be the case with array_walk
.
The main reasons I prefer to use array_walk
are clarity, type-hinting and scoping.
<?php
array_walk($data, "trim");