Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP: replace array value doesn't stay after foreach loop

I'm changing the value in a multi-dimensional array and it's not staying outside of the foreach loop that's being used to traverse it.

My array initially looks something like this:

Array
{
  [0] => Array
   {
     [name] => Bob
     [age] => 33
     [state] => CA
     [visited] => 0
   }
   ...
}

My PHP gets into it by going:

foreach ($people as $person){
 echo $person['name']
 ....
 logic for the visited variable
 ...
 $person['visited'] = $calculated_visit_value;
}

If I

print_r($person)

at the end (but inside) of the foreach loop everything looks good, the value for visited is set. However, if I print_r($people) outside of the loop, $person['visited'] is not set. I don't know what I'm doing wrong.

Help is appreciated.

like image 312
mikepreble Avatar asked Jul 19 '11 22:07

mikepreble


2 Answers

You are creating a new variable called $person from within that for loop and your array will never see the scope of that new variable.

You can try passing it by reference, like so:

foreach ($people as &$person){
 echo $person['name'];
 ....
 logic for the visited variable
 ...
 $person['visited'] = $calculated_visit_value;
}
like image 123
AlienWebguy Avatar answered Nov 01 '22 10:11

AlienWebguy


From foreach's documentation:

Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer. Don't rely on the array pointer during or after the foreach without resetting it.

What this means is that your $person variable is a copy of what was in the array, similar in effect to this code (note that this code is for understanding only and wrong on many levels, in reality you would use the reset(), current() and next() function to loop properly over your array, see here):

for ($i = 0; $i < count($people); $i++) {
  $person = $people[$i];
  // code inside your foreach ...
}

So if you change the content of $person, you don't actually modify what's inside the $people array

To solve that, you can either use a referenced foreach:

foreach ($people as &$person) { // note the &
  $person = $calculated_visit_value; // $person is now a reference to the original value inside $people and thus this will work as intended
}

Note that the refence is not cleared when the foreach loop ends, so at the end of it $person is still a reference to the last element of $people. If you don't know what references are, please refer to the documentation for more info.

Or use the key to access the original array:

foreach ($people as $person_index => $person) {
  $people[$person_index] = $calculated_visit_value;
}

For your information, you can use the two together

foreach ($people as $person_index => &$person { ...
like image 3
Lepidosteus Avatar answered Nov 01 '22 09:11

Lepidosteus