note 92116 added to control-structures.foreach

From: Date: Thu, 09 Jul 2009 11:50:02 +0000
Subject: note 92116 added to control-structures.foreach
Groups: php.notes 
Request: Send a blank email to php-notes+get-158101@lists.php.net to get a copy of this message
The weird behaviour of references in foreach remains as long as in PHP 5.2.08 (Linux) and PHP 5.2.9 (Windows XP). The simplest example would be: <?php $a = array('a', 'b','c'); foreach($a as &$row){ //you don't have to do anything here } print_r($a); foreach($a as $row){ echo "<br />".$row; } ?> the result of print_r will be correct - array of ('a','b','c') values. The second foreach, however, would produce a,b,b. For all arrays, regardless of size, it would be the n-1 element (the element right before the last one). Eg. for 'a','b','c','d','e','f', the script would produce a,b,c,d,e,e. There are few solutions to this: 1. safest - avoid using references in foreach; so instead of <?php foreach($a as &$row){ // do something, eg. $row = trim($row); } ?> you would use <?php foreach($a as $i=>$row){ // do something on row, eg. $row = trim($row); // replace the row in the table $a[$i]=$row; } ?> decrease of performance is the cost, however 2. equally safe and more usable - unset the element reference right after the foreach loop with references, eg.: <?php $a = array('a', 'b','c'); foreach($a as &$row){ //you don't have to do anything here } unset ($row)); // it is safe now to use $row again print_r($a); foreach($a as $row){ echo "<br />".$row; } ?> 3. use references in both case; it seems that iterations work correct if you use &$row in both loops or don't use it in any: <?php $a = array('a', 'b','c'); foreach($a as &$row){ //you don't have to do anything here } print_r($a); // works OK now even without unset($row) foreach($a as &$row){ echo "<br />".$row; } ?> 4. use references in foreach only inside functions or methods; outside the function scope it should be safe <?php function cleanTable($a){ foreach($a as &$row){ $row = trim($row); } } $a = array('a','b','c'); cleanTable($a); foreach($a as $row){ echo "<br />".$row; } ?> drawbacks: NONE! I Quite contrary, the code looks more tidy. 5. avoid using the same variable names for referenced and non-referenced values; for example, in the first case use &$rRow, and in the second one - $row. It's neither elegant, nor efficient, though, as each new variable lowers the application performance a bit. <?php $a = array('a', 'b','c'); foreach($a as &$rRow){ // $rRow for 'referenced row' //you don't have to do anything here } print_r($a); foreach($a as $row){ echo "<br />".$row; } ?> ---- Server IP: 194.24.174.37 Probable Submitter: 89.79.61.55 ---- Manual Page -- http://www.php.net/manual/en/control-structures.foreach.php Edit -- https://master.php.net/note/edit/92116 Del: integrated -- https://master.php.net/note/delete/92116/integrated Del: useless -- https://master.php.net/note/delete/92116/useless Del: bad code -- https://master.php.net/note/delete/92116/bad+code Del: spam -- https://master.php.net/note/delete/92116/spam Del: non-english -- https://master.php.net/note/delete/92116/non-english Del: in docs -- https://master.php.net/note/delete/92116/in+docs Del: other reasons-- https://master.php.net/note/delete/92116 Reject -- https://master.php.net/note/reject/92116 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#158101) next »