Josh Stone, Blog

Josh’s projects and security nerdery

PHP4 Foreach Blocks

This was just annoying enough that I have to write about it to blow off some steam. I’m implementing some ADTs in PHP for work. One of these is a certain type of tree where I am using an array to store a node’s children. Each node is an object, in good OO form.

But I was having a very strange bug, and couldn’t figure it out. The first level of the tree could add children, but the second (and farther) could not. I’d add a child and it would disappear completely.

After a few minutes, I realized that it was a passing-by-value problem. I guess I’m just too used to languages where objects are passed by reference, and PHP defaults to passing objects by value. It took me almost an hour to find exactly where and why.

See, in PHP4, one can mark incoming variables to a function as passed by reference (&$var instead of $var). This is great, I thought, but I’m not passing any objects to functions — I’m just calling methods on objects. And then it hit me. I was using a foreach() block to iterate through a node’s children, as below:

foreach($this->children as $i)
   ... $i->meth ...

The $i variable is passed by value into the block. Go fig. So PHP4 supports passing by reference or value into functions, but it is not until PHP5 that the syntax for passing by reference into a foreach() was implemented. Argh.

Sometimes, I like PHP, and it seems like a perfectly good language for stapling templates together. Then, every once in a while, I decide to do something more complex and I end up continually mystified at the design decisions made in the history of the language. And why, oh why, didn’t somebody think when adding pass-by-reference syntax to include foreach() blocks?!?

But, fortunately, this works, since I won’t be seeing PHP5 on that server for awhile:

for($x=0; $xchildren); $x++)
   ... $this->children[$x]->meth ...