20

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?

Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
Brenn
  • 211
  • 2
  • 4

2 Answers2

39

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

NikiC
  • 100,734
  • 37
  • 191
  • 225
  • 3
    +1 for answering the question, but he doesnt really need to loop by reference since he is working with objects... does he? – prodigitalson Apr 27 '11 at 20:35
  • 1
    @prodigitalson: Yep, you're right. ^^ I'm always thinking too comlicated – NikiC Apr 27 '11 at 20:40
  • haha.. it happens (to me more often than id liek to admit). you did answer the question though which is important when one does need to loop by reference. – prodigitalson Apr 27 '11 at 20:45
  • Thank you! I was tearing my hair out about this. I actually wrote a workaround in the meantime, but I've come across this weirdness a few times and never understood it. GREAT link BTW. – Brenn Apr 28 '11 at 18:44
  • 3
    @Brenn: If this answer answers your question, you should accept it, by clicking on the green tick next to it :) – NikiC Apr 28 '11 at 20:04
  • @NikiC, (@Brenn) Was also just tearing my hair out over this one. Learned something valuable tonight- would up vote this twice if I could. – barfoon Jul 12 '12 at 04:09
4

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.

HappyDeveloper
  • 12,480
  • 22
  • 82
  • 117