title: Strange behavior of unset in foreach by reference loop
body: <p>I know one should not modify physical structure of array while looping by reference, but I need explanation of what is going on in my code. Here we go:</p>
  
  <pre><code>$x= [[0],[1],[2],[3],[4]];
  foreach ($x as $i =&gt; &amp;$upper) {
      print $i;
      foreach ($x as $j =&gt; &amp;$lower) {
  
          if($i == 0 &amp;&amp; $j == 2) {
              unset($x[2]);
          } else if($i == 1 &amp;&amp; $j == 3) {
              unset($x[3]);
          }
      }
  }
  </code></pre>
  
  <p>The output is <code>01</code>. Surprising that outer loop iterates only twice, for indices <code>0</code> and <code>1</code>. I was expecting the output to be <code>014</code>.</p>
  
  <p>I have read lots of blog posts and questions about hazards of using array references, but nothing that can explain this phenomenon. I am breaking my head over it for hours now.</p>
  
  <h1>EDIT:</h1>
  
  <p>The code above is the minimal reproducible code. One explanation (but an <em>incorrect</em> one) that might seem to be the case is this:</p>
  
  <p><em>The outer loop goes through two iterations before the internal pointer is set to index <code>2</code>. But the loop does not find any element at index <code>2</code> and thus thinks no elements are left and quits.</em></p>
  
  <p>The problem with this theory is it doesn't quite explain this code:</p>
  
  <pre><code>$x= [[0],[1],[2],[3],[4]];
  foreach ($x as $i =&gt; &amp;$upper) {
      print $i;
      foreach ($x as $j =&gt; &amp;$lower) {
  
          if($i == 0 &amp;&amp; $j == 2) {
              unset($x[2]);
              // No if else here
              unset($x[3]);
          }
      }
  }
  </code></pre>
  
  <p>By the same token, the above code should also produce <code>01</code>, but its actual output is <code>014</code>, as expected. Even when two items in a series are removed, php knows that are still elements left to be iterated over. Could this possibly be a bug with php scripting engine?</p>