Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does PHP's foreach advance the pointer of its array (only) once?

Tags:

php

This is a question of curiosity about the reasons behind the way foreach is implemented within PHP.

Consider:

$arr = array(1,2,3);
foreach ($arr as $x) echo current($arr) . PHP_EOL;

which will output:

2
2
2

I understand that foreach rewinds array pointers to the beginning; however, why does it then increment it only once? What is happening inside the magic box?? Is this just an (ugly) artefact?


Thanks @NickC -- for anyone else curious about zval and refcount, you can read up on the basics here

like image 658
jlb Avatar asked Nov 24 '11 23:11

jlb


1 Answers

Right before the first iteration the $array is "soft copied" for use in foreach. This means that no actual copy is done, but only the refcount of the zval of $array is increased to 2.

On the first iteration:

  1. The value is fetched into $x.
  2. The internal array pointer is moved to the next element, i.e. now points to 2.
  3. current is called with $array passed by reference. Due to the reference PHP cannot share the zval with the loop anymore and it needs to be separated ("hard copied").

On the following iterations the $array zval thus isn't anymore related the the foreach zval anymore. Thus its array pointer isn't modified anymore and current always returns the same element.

By the way, I have written a small summary on foreach copying behavior. It might be of interest in the context, but it does not directly relate to the issue as it talks mostly about hard copying.

like image 141
NikiC Avatar answered Oct 23 '22 04:10

NikiC