I ran into a weird issue and could reproduce it with this snippet:
<?php
$arr = [];
for($i = 0; $i <= 3; $i ) {
$arr[] = [
$i
];
}
foreach ($arr as &$item) {
$item[] = $item[0];
}
foreach ($arr as $item) {
print_r($item);
}
It is outputting (notice the last element had been replaced with a copy of its previous one):
Array
(
[0] => 0
[1] => 0
)
Array
(
[0] => 1
[1] => 1
)
Array
(
[0] => 2
[1] => 2
)
Array
(
[0] => 2
[1] => 2
)
However, here's the expected result:
Array
(
[0] => 0
[1] => 0
)
Array
(
[0] => 1
[1] => 1
)
Array
(
[0] => 2
[1] => 2
)
Array
(
[0] => 3
[1] => 3
)
If I use array_map instead of the first foreach, it works:
<?php
$arr = [];
for($i = 0; $i <= 3; $i ) {
$arr[] = [
$i
];
}
$arr = array_map(function ($item) {
$item[] = $item[0];
return $item;
}, $arr);
foreach ($arr as $item) {
print_r($item);
}
Tested under PHP 8.0.0.
What could be causing this difference? Is there something about array pointers I'm missing?
CodePudding user response:
$arr = [];
for($i = 0; $i <= 3; $i ) {
$arr[] = [
$i
];
}
/** Output
* $arr = [[0],[1],[2],[3]]
*/
In this foreach loop you are just selecting the existing value of item and setting it into a new index of referenced item
foreach ($arr as &$item) {
$item[] = $item[0];
}
Type of $item is array, $item[0] is referred to its 0 index $item[] means a new array index inside item that is currently referenced to.
CodePudding user response:
In your first example, the $item variable still holds a reference to the last value of the $arr when the loop is done.
foreach ($arr as &$item) {
$item[] = $item[0];
}
If you use print_r(get_defined_vars()); you can see that there is a key in the array with name item
The behaviour of the double value at the end of the foreach is described here and It is recommended to destroy the specified variables using unset($item)
You can also use a different variable name.
Using array_map, the callback gets a function argument passed by name, which is bound to the function scope.
If you run print_r(get_defined_vars()); after using array_map you can see that there is no key named item
