I have a coworker that I noticed was using his foreachs in the following fashion:
foreach ($var as $var) {
// do stuff here
}
I have tested the code above and it works correctly to my surprise. Would the PHP gurus like to hop in and tell me why this is wrong? It feels very wrong.
Because it changes the value of $var
. After the foreach()
it's no longer an array but is set to the last value in the array.
$var = array('apple', 'orange');
foreach ($var as $var) {
echo $var."<br/>";
}
echo $var; //orange
If you don't want to change the variable's value, it'll need to be a different variable name:
$var = array('apple', 'orange');
foreach ($var as $fruit) {
echo $fruit."<br/>";
}
echo $var; //array
As @UselessIntern pointed out, it's fine if you're not going to use the variable after looping through it, but it's definitely not encouraged because it can lead to confusion.
As @PLB pointed out, it iterates over a copy of the $var
not $var
itself. So every iteration the value of $var
is changing, but it doesn't break the loop because it's looping over the copy that was created.
Even it feels wrong, it still works because the moment the foreach
starts, PHP internally has already access on the data.
So even $var
gets overwritten, in memory this data is still present (the original array) and $var
is set in each iteration to the current value of it.
The concrete problem you've spotted and about which you say is wrong is also known as variable-reuse which you should prevent because this is a code-smell.
It not only feels wrong, it is wrong to write such code. Tell your co-worker so you can write better code together.
Because it's a loop. Performing:
array > string
array > string
So
foreach ($var AS $var){
/*
Is basically being re-read at the end so your foreach can read the array again to get the next step of the array
array > string
recheck array > string
recheckarray > string
*/
}
Check this expression:
$x = array(1,2,3);
foreach ($x as $x) {
echo $x; //prints 123
}
What is happening here is that the foreach
extracts the first element of array $x
and overrides into $x
itself. However the array variable $x
which was on the left side of the as
keyword remains in internal scope of the foreach
argument which is why the looping works without problems.
Once the loop completes the $x
which was internal to the foreach
(the array) loses scope and no longer exists, and what remains is the $x variable
which now contains the last element of the original $x array
. In this case that would be 3
.
Your coworker seems to don't need $var
as an array after the loop anymore. When PHP initializes the foreach loop (what is done only once) it uses the original values from $var
as it is an array at the moment. Then on every step in the loop the current element of the element is assigned to a new var called var
. Note that the orginal array $var
doesn't exist anymore. After the loop $var
will have the value of the last element in the original array.
check this little example which demonstrates what I've said:
$a = array(1,2,3);
foreach($a as $a) {
echo var_dump($a);
}
// after loop
var_dump($a); // integer(3) not array
I could imaging that your coworker does this to save a little memory as the reference to the array will get overwritten and therefore the garbage collector will remove it's memory on next run, but I would not advice you to do the same, as it's less readable.
Just do the following, which is the same but is much more readable:
$array = array(1,2,3);
foreach($array as $value) {
echo var_dump($value);
}
delete($array);
delete($value);