note 67264 added to function.reset
| From: | Colin at osu1 dot php dot net | Date: | Tue, 06 Jun 2006 15:11:20 +0000 |
| Subject: | note 67264 added to function.reset | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-113362@lists.php.net to get a copy of this message | ||
I had a problem with PHP 5.0.5 somehow resetting a sub-array of an array with no apparent reason.
The problem was in doing a foreach() on the parent array PHP was making a copy of the subarrays and
in doing so it was resetting the internal pointers of the original array.
The following code demonstrates the resetting of a subarray:
<?
$a = array(
'a' => array(
'A', 'B', 'C', 'D',
),
'b' => array(
'AA', 'BB', 'CC', 'DD',
),
);
// Set the pointer of $a to 'b' and the pointer of 'b' to 'CC'
reset($a);
next($a);
next($a['b']);
next($a['b']);
next($a['b']);
var_dump(key($a['b']));
foreach($a as $k => $d)
{
}
var_dump(key($a['b']));
?>
The result of the two var dumps are 3 and 0, respectively. Clearly the internal pointer of
$a['b'] was reset by doing the foreach loop over $a.
Each time the foreach loop iterated over the 'a' and 'b' keys of $a it made a
copy of $a['a'] and $a['b'] into $d which resetted the internal pointers of
$a['a'] and $a['b'] despite making no obvious changes.
The solution is instead to iterate over the keys of $a.
<?
foreach(array_keys($a) as $k)
{
}
?>
and using $a[$k] (or creating an alias of $a[$k] as $d and dealing with the consequences of using
aliases).
For the curious, I was implementing the Iterator interface on a dummy object and calling a global
object to do the actual iteration (also to cope with PHP's lack of C-style pointers which when
doing a $a = $b on objects would cause the data in $a to be inconsistent with the data in $b when
modified). Being that I had many dummy objects representing different data sets I chose to store
each data set as a subarray contained within the global object. To make this work each dummy object
has to store a key (which can freely be duplicated without problems) that it passes to the global
object when rewind, key, current, next, and valid were called on the dummy object.
Unfortunately for me, my key required to be more than just a simple string or number (if it was then
it could be used to directly index the subarray of data for that object and problem avoided) but was
an array of strings. Instead, I had to iterate over (with a foreach loop) each subarray and compare
the key to a variable stored within the subarray.
So by using a foreach loop in this manner and with PHP resetting the pointer of subarrays it ended
up causing an infinite loop.
Really, this could be solved by PHP maintaining internal pointers on arrays even after copying.
----
Server IP: 64.71.164.2
Probable Submitter: 65.125.133.211
----
X-Spam-Status: No, hits=3.1 required=5.0 tests=DATE_MISSING,FROM_NO_LOWER
autolearn=no version=2.64
----
Manual Page -- http://www.php.net/manual/en/function.reset.php
Edit -- http://master.php.net/note/edit/67264
Del: integrated -- http://master.php.net/note/delete/67264/integrated
Del: useless -- http://master.php.net/note/delete/67264/useless
Del: bad code -- http://master.php.net/note/delete/67264/bad+code
Del: spam -- http://master.php.net/note/delete/67264/spam
Del: non-english -- http://master.php.net/note/delete/67264/non-english
Del: in docs -- http://master.php.net/note/delete/67264/in+docs
Del: other reasons-- http://master.php.net/note/delete/67264
Reject -- http://master.php.net/note/reject/67264
Search -- http://master.php.net/manage/user-notes.php