Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavior Of foreach

<?php   $a = array('a', 'b', 'c', 'd');    foreach ($a as &$v) { }   foreach ($a as $v) { }    print_r($a); ?> 

I think it's a normal program but this is the output I am getting:

Array (     [0] => a     [1] => b     [2] => c     [3] => c ) 

Can someone please explain this to me?

like image 302
Manish Trivedi Avatar asked Feb 11 '11 12:02

Manish Trivedi


People also ask

Is foreach deprecated?

Warning This function has been DEPRECATED as of PHP 7.2. 0. Relying on this function is highly discouraged.

Is foreach faster than while?

There is no major "performance" difference, because the differences are located inside the logic. You use foreach for array iteration, without integers as keys. You use for for array iteration with integers as keys. etc.

What is the meaning of foreach?

Foreach is a loop statement in the Perl programming language that executes once for each value of a data object. It takes the general form: foreach thing (in object) { do something; do something else; }

Is foreach slower than for PHP?

The 'foreach' is slow in comparison to the 'for' loop. The foreach copies the array over which the iteration needs to be performed. For improved performance, the concept of references needs to be used.


1 Answers

This is well-documented PHP behaviour See the warning on the foreach page of php.net

Warning

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

$a = array('a', 'b', 'c', 'd');  foreach ($a as &$v) { } unset($v); foreach ($a as $v) { }  print_r($a); 

EDIT

Attempt at a step-by-step guide to what is actually happening here

$a = array('a', 'b', 'c', 'd'); foreach ($a as &$v) { }   // 1st iteration $v is a reference to $a[0] ('a') foreach ($a as &$v) { }   // 2nd iteration $v is a reference to $a[1] ('b') foreach ($a as &$v) { }   // 3rd iteration $v is a reference to $a[2] ('c') foreach ($a as &$v) { }   // 4th iteration $v is a reference to $a[3] ('d')                            // At the end of the foreach loop,                           //    $v is still a reference to $a[3] ('d')  foreach ($a as $v) { }    // 1st iteration $v (still a reference to $a[3])                            //    is set to a value of $a[0] ('a').                           //    Because it is a reference to $a[3],                            //    it sets $a[3] to 'a'. foreach ($a as $v) { }    // 2nd iteration $v (still a reference to $a[3])                            //    is set to a value of $a[1] ('b').                           //    Because it is a reference to $a[3],                            //    it sets $a[3] to 'b'. foreach ($a as $v) { }    // 3rd iteration $v (still a reference to $a[3])                            //    is set to a value of $a[2] ('c').                           //    Because it is a reference to $a[3],                            //    it sets $a[3] to 'c'. foreach ($a as $v) { }    // 4th iteration $v (still a reference to $a[3])                            //    is set to a value of $a[3] ('c' since                            //       the last iteration).                           //    Because it is a reference to $a[3],                            //    it sets $a[3] to 'c'. 
like image 86
Mark Baker Avatar answered Oct 04 '22 14:10

Mark Baker