Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP foreach by reference causes weird glitch when going through array of objects

Tags:

foreach

php

I have an array of objects. The objects mainly have a bunch of properties because these are meta-data objects.

so it is like $objects[] is like a bunch of items that have properties like: object->item1, object->item2, etc.

I want to add something to each of these objects, so...

foreach ($objects as &$object) {
  $object->newItem=(something I compute);
}

then later, I want to display these objects as a list in html. So, I go:

foreach ($objects as $object) {
  <li><?php object output stuff here ?></li>
}

ok. Now, it works fine, except the last object is discarded and the second to last object is displayed twice. WTF??

Does this make sense to you?

like image 956
Brenn Avatar asked Apr 27 '11 20:04

Brenn


People also ask

Is foreach slower than for PHP?

In short: foreach is faster than foreach with reference. foreach is faster than for. foreach is faster than for for a hash table.

Which is faster for loop or foreach in PHP?

The foreach loop is considered to be much better in performance to that of the generic for loop. The foreach loop though iterates over an array of elements, the execution is simplified and finishes the loop in less time comparatively.

What is $value in foreach?

foreach ($array as $value) { code to be executed; } For every loop iteration, the value of the current array element is assigned to $value and the array pointer is moved by one, until it reaches the last array element.

Can you break a foreach loop PHP?

To terminate the control from any loop we need to use break keyword. The break keyword is used to end the execution of current for, foreach, while, do-while or switch structure.


2 Answers

If you iterate by reference, always unset the iteration variable afterwards:

foreach ($objects as &$object) {
      // some code
}
unset($object);

Excerpt from the foreach documentation:

Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().

If you want to understand why your code behaves the way it behaves, here is some further reading: References and foreach

like image 53
NikiC Avatar answered Sep 24 '22 21:09

NikiC


Objects are always references, so just remove the '&'

foreach ($objects as $object) {
  $object->newItem=(something I compute);
}

foreach ($objects as $object) {
  echo "<li>{$object->someResult()}</li>";
}

I know you already got your answer, but this might help other devs find it faster.

like image 36
HappyDeveloper Avatar answered Sep 23 '22 21:09

HappyDeveloper