For gurus: bug in php? Recursive foreach dont work properly.
Question posted by: Tamagafk
(Guest)
on
April 12th, 2007 09:05 AM
Hi! Looks like there is a bug in php. If I have function which uses
foreach to run trough array recursively, the lop-level foreach
interupted by lover-level foreach'es. If I use simply 'for' everything
is ok. Example:
I have an array of 3 objects connected hierarchically by their
variables id and parentId, here is the hierarchy:
id=1 parentId=0
....id=2 parentId=1
....id=3 parentId=1
I start digging from item with id=1 down to its chils and top-level
foreach NEVER REACH ELEMENT 3!!! Top-level foreach just stops.
<?php
function prn($s){
echo($s.'<br>');
}
$nodes = array();
$nodes[0] = new node(1, 0);
$nodes[1] = new node(2, 1);
$nodes[2] = new node(3, 1);
$nodes[3] = new node(4, 0);
class node{
var $id;
var $parentId;
function node($id, $parentId){
$this->id = $id;
$this->parentId = $parentId;
}
function dig($level){
global $nodes;
$l = '';
for($i=0; $i<$level; $i++) $l.='..';
prn($l.'looking for childs of '.$this->id.' {');
foreach($nodes as $n){
prn($l.$n->id.' (parent '.$n->parentId.')');
if($n->parentId == $this->id){
$n->dig($level+1);
}
}
prn($l.'}');
}
}
$nodes[0]->dig(0);
?>
The output should look like this:
looking for childs of 1 {
1 (parent 0)
2 (parent 1)
...looking for childs of 2 {
...1 (parent 0)
...2 (parent 1)
...3 (parent 1)
...}
3 (parent 1)
...looking for childs of 3 {
...1 (parent 0)
...2 (parent 1)
...3 (parent 1)
...}
}
But it looks like this:
looking for childs of 1 {
1 (parent 0)
2 (parent 1)
...looking for childs of 2 {
...1 (parent 0)
...2 (parent 1)
...3 (parent 1)
...}
}
13
Answers Posted
One more thing: pretend that there is no $nodes[3] = new node(4, 0);
:)
Tamagafk wrote:
Quote:
Originally Posted by
Hi! Looks like there is a bug in php. If I have function which uses
foreach to run trough array recursively, the lop-level foreach
interupted by lover-level foreach'es. If I use simply 'for' everything
is ok.
It's not a bug -- it's a "feature". Internally, arrays in PHP have a
"pointer" (not in the C sense of the word) which points at the "current"
element of array. foreach() uses this pointer to iterate through the
array. This is alluded to in the manual:
"the internal pointer of the original array *is*
advanced with the processing of the array."
So both foreach() functions are playing with the same internal pointer,
and screw things up for each other.
As an aside, you can use this internal pointer yourself via the following
functions:
each() - Returns current key, value pair
key() - Returns current key
current() - Returns current value
reset() - Reset pointer to start, return value
next() - Move pointer forwards, return value
prev() - Move pointer backwards, return value
end() - Move pointer to end, return value
Anyway, one solution is to either use for(), as you've discovered. This
works because instead of using PHP's internal array pointer to keep track
of your position in the array, you've defined your own pointer.
The other solution is to make a local copy of the array and run your
foreach() loop on that. Using for() is probably neater though.
--
Toby A Inkster BSc (Hons) ARCS
Contact Me ~ http://tobyinkster.co.uk/contact
Geek of ~ HTML/SQL/Perl/PHP/Python*/Apache/Linux
* = I'm getting there!
"Toby A Inkster" <usenet200703@tobyinkster.co.ukwrote in message
news:gr81f4-4kp.ln1@ophelia.g5n.co.uk...
Quote:
Originally Posted by
Tamagafk wrote:
>
Quote:
Originally Posted by
Hi! Looks like there is a bug in php. If I have function which uses
foreach to run trough array recursively, the lop-level foreach
interupted by lover-level foreach'es. If I use simply 'for' everything
is ok.
>
It's not a bug -- it's a "feature". Internally, arrays in PHP have a
"pointer" (not in the C sense of the word) which points at the "current"
Why not in the "C sense"?
Something similar to an itterator in C++ ?
TIA
Vince
Vince Morgan kirjoitti:
Quote:
Originally Posted by
"Toby A Inkster" <usenet200703@tobyinkster.co.ukwrote in message
news:gr81f4-4kp.ln1@ophelia.g5n.co.uk...
Quote:
Originally Posted by
>Tamagafk wrote:
>>
Quote:
Originally Posted by
>>Hi! Looks like there is a bug in php. If I have function which uses
>>foreach to run trough array recursively, the lop-level foreach
>>interupted by lover-level foreach'es. If I use simply 'for' everything
>>is ok.
>It's not a bug -- it's a "feature". Internally, arrays in PHP have a
>"pointer" (not in the C sense of the word) which points at the "current"
>
Why not in the "C sense"?
Well it's not like a pointer in C. In C your basic arrays (or strings
which are just arrays of characters) are pointers to memory locations,
and the index is an offset. Since PHP works at a higher level, it
doesn't know anything about the memory, so pointers in that sense don't
exist in php. However the datastructure of an array has an internal
"pointer" but it doesn't mean the same as pointers in C.
See http://en.wikipedia.org/wiki/Pointer_%28computing%29
--
Join Bytes!
"Wikipedia on vähän niinq internetin raamattu, kukaan ei pohjimmiltaan
usko siihen ja kukaan ei tiedä mikä pitää paikkansa." -- z00ze
Vince Morgan wrote:
Quote:
Originally Posted by
"Toby A Inkster" <usenet200703@tobyinkster.co.ukwrote in message
news:gr81f4-4kp.ln1@ophelia.g5n.co.uk...
Quote:
Originally Posted by
>Tamagafk wrote:
>>
Quote:
Originally Posted by
>>Hi! Looks like there is a bug in php. If I have function which uses
>>foreach to run trough array recursively, the lop-level foreach
>>interupted by lover-level foreach'es. If I use simply 'for' everything
>>is ok.
>It's not a bug -- it's a "feature". Internally, arrays in PHP have a
>"pointer" (not in the C sense of the word) which points at the "current"
>
Why not in the "C sense"?
Something similar to an itterator in C++ ?
>
TIA
Vince
>
>
Vince,
Because in C a pointer is a memory location. It's not in PHP - just an
indicator to the current location in an array.
And no, it's not like an iterator - there are no methods you can use on
the internal pointer - only the array itself.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
Join Bytes!
==================
Jerry Stuckle kirjoitti:
Quote:
Originally Posted by
And no, it's not like an iterator - there are no methods you can use on
the internal pointer - only the array itself.
Sigh... In the previous post Toby listed all the methods that can be
used on the internal pointer... So there are indeed methods for
manipulating the internal pointer, but the internal pointer is not like
an iterator in C++. :)
--
Join Bytes!
"Wikipedia on vähän niinq internetin raamattu, kukaan ei pohjimmiltaan
usko siihen ja kukaan ei tiedä mikä pitää paikkansa." -- z00ze
Vince Morgan wrote:
Quote:
Originally Posted by
Toby A Inkster wrote:
>
Quote:
Originally Posted by
>It's not a bug -- it's a "feature". Internally, arrays in PHP have a
>"pointer" (not in the C sense of the word) which points at the "current"
>
Why not in the "C sense"?
A pointer in the C sense of the word is (more or less) an exact memory
address for a piece of data.
The internal pointer in a PHP array has a far more ethereal nature.
Exactly how it works is an enigma wrapped in a riddle and shrouded by
mystery. We don't have direct access to the pointer, but can see its
ghostly effects in the list of functions I mentioned in my previous
post.
It's exact implementation in the PHP source code may well be as a C
pointer, but that doesn't (and shouldn't) matter to a person who's using
PHP arrays. The internal implementation as might well change for each new
version of PHP which is released -- as far as they're concerned, it
doesn't matter, as long as each(), next() and so on keep working as they
do.
Quote:
Originally Posted by
Something similar to an itterator in C++ ?
The array is, yes.
PHP 5 has iterators too.
--
Toby A Inkster BSc (Hons) ARCS
Contact Me ~ http://tobyinkster.co.uk/contact
Geek of ~ HTML/SQL/Perl/PHP/Python*/Apache/Linux
* = I'm getting there!
"Vince Morgan" <vinhar@REMOVEoptusnet.com.auwrote in message
news:461e08a4$0$9771$afc38c87@news.optusnet.com.au ...
Quote:
Originally Posted by
"Toby A Inkster" <usenet200703@tobyinkster.co.ukwrote in message
news:gr81f4-4kp.ln1@ophelia.g5n.co.uk...
Quote:
Originally Posted by
Tamagafk wrote:
Quote:
Originally Posted by
Hi! Looks like there is a bug in php. If I have function which uses
foreach to run trough array recursively, the lop-level foreach
interupted by lover-level foreach'es. If I use simply 'for' everything
is ok.
It's not a bug -- it's a "feature". Internally, arrays in PHP have a
"pointer" (not in the C sense of the word) which points at the "current"
>
Why not in the "C sense"?
Something similar to an itterator in C++ ?
>
TIA
Vince
>
I guess I didn't ask that q very well at all.
I'm familiar with pointers in C/C++, and iterators in C++, they are
languages I have most experience with.
However, I was thinking that they may be in some ways similar to say, a
vector iterator, without regard for methods etc.
I meant in a very general way, but I think it was probably a silly question
realy.
Trying to cheat my way into a greater understanding of the unerlying
implementation without doing the reading I guess ;)
Thank you for the reply though,
Regards,
Vince
"Toby A Inkster" <usenet200703@tobyinkster.co.ukwrote in message
news:ivg1f4-4kp.ln1@ophelia.g5n.co.uk...
Quote:
Originally Posted by
Vince Morgan wrote:
Quote:
Originally Posted by
Toby A Inkster wrote:
Quote:
Originally Posted by
It's not a bug -- it's a "feature". Internally, arrays in PHP have a
"pointer" (not in the C sense of the word) which points at the
"current"
Quote:
Originally Posted by
Quote:
Originally Posted by
Why not in the "C sense"?
>
A pointer in the C sense of the word is (more or less) an exact memory
address for a piece of data.
>
The internal pointer in a PHP array has a far more ethereal nature.
Exactly how it works is an enigma wrapped in a riddle and shrouded by
mystery. We don't have direct access to the pointer, but can see its
ghostly effects in the list of functions I mentioned in my previous
post.
Those functions had a sic "ghostly" likeness to a C++ vector and I was
wondering if in fact a vector may be used in the underlying implementation.
Quote:
Originally Posted by
It's exact implementation in the PHP source code may well be as a C
pointer, but that doesn't (and shouldn't) matter to a person who's using
PHP arrays. The internal implementation as might well change for each new
version of PHP which is released -- as far as they're concerned, it
doesn't matter, as long as each(), next() and so on keep working as they
do.
My first problem in going from C to C++ was that I didn't "own" the pointers
of the library objects, so I appreciate what your saying here.
Quote:
Originally Posted by
>
Quote:
Originally Posted by
Something similar to an itterator in C++ ?
>
The array is, yes.
That's what I was imagining might be below the surface.
Thank you for taking the time Toby,
Vince
"Toby A Inkster" <usenet200703@tobyinkster.co.ukwrote in message
news:ivg1f4-4kp.ln1@ophelia.g5n.co.uk...
| Vince Morgan wrote:
| Toby A Inkster wrote:
| >
| >It's not a bug -- it's a "feature". Internally, arrays in PHP have a
| >"pointer" (not in the C sense of the word) which points at the
"current"
| >
| Why not in the "C sense"?
|
| A pointer in the C sense of the word is (more or less) an exact memory
| address for a piece of data.
|
| The internal pointer in a PHP array has a far more ethereal nature.
| Exactly how it works is an enigma wrapped in a riddle and shrouded by
| mystery. We don't have direct access to the pointer, but can see its
| ghostly effects in the list of functions I mentioned in my previous
| post.
ethereal?
let's say an enumerable object inherits an 'ienumerable' class. that
interface simply has a getEnumerator() function which php calls natively
when the code uses things like foreach(). getEnumerator() returns an
'ienumerator' object that defines the reset(), each(), key(), etc..
for all of that, ienumerator only has 2 variables. one for the array of
items, and one representing the current index. reset() just sets the index
to 0, each() increments, etc., etc.. none of that is brain surgurery and is
a common practice in object C, C++, VB, etc. whenever you want to strongly
type your own 'collection' to speed things up and enforce your variables'
integrity a bit more. it's not mysterious in any way.
:)
Rami Elomaa wrote:
Quote:
Originally Posted by
Jerry Stuckle kirjoitti:
>
Quote:
Originally Posted by
>And no, it's not like an iterator - there are no methods you can use
>on the internal pointer - only the array itself.
>
Sigh... In the previous post Toby listed all the methods that can be
used on the internal pointer... So there are indeed methods for
manipulating the internal pointer, but the internal pointer is not like
an iterator in C++. :)
>
No, the methods are operating on the array, not the internal pointer.
You have no direct access to the internal pointer.
For instance, you use next(array), not pointer.next() as you would with
a C++ iterator.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
Join Bytes!
==================
Vince Morgan wrote:
Quote:
Originally Posted by
"Vince Morgan" <vinhar@REMOVEoptusnet.com.auwrote in message
news:461e08a4$0$9771$afc38c87@news.optusnet.com.au ...
Quote:
Originally Posted by
>"Toby A Inkster" <usenet200703@tobyinkster.co.ukwrote in message
>news:gr81f4-4kp.ln1@ophelia.g5n.co.uk...
Quote:
Originally Posted by
>>Tamagafk wrote:
>>>
>>>Hi! Looks like there is a bug in php. If I have function which uses
>>>foreach to run trough array recursively, the lop-level foreach
>>>interupted by lover-level foreach'es. If I use simply 'for' everything
>>>is ok.
>>It's not a bug -- it's a "feature". Internally, arrays in PHP have a
>>"pointer" (not in the C sense of the word) which points at the "current"
>Why not in the "C sense"?
>Something similar to an itterator in C++ ?
>>
>TIA
>Vince
>>
>
I guess I didn't ask that q very well at all.
I'm familiar with pointers in C/C++, and iterators in C++, they are
languages I have most experience with.
However, I was thinking that they may be in some ways similar to say, a
vector iterator, without regard for methods etc.
I meant in a very general way, but I think it was probably a silly question
realy.
Trying to cheat my way into a greater understanding of the unerlying
implementation without doing the reading I guess ;)
Thank you for the reply though,
Regards,
Vince
>
>
Vince,
But the whole point of an iterator is that it has methods you can use to
manipulate it. The PHP internal pointer does not - you can only
manipulate the pointer through the array itself.
Additionally, you can define multiple (or no) iterators for the same
list/array/whatever because it is a separate object. But in PHP you
have exactly one pointer which is tied to the array.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
Join Bytes!
==================
"Jerry Stuckle" <jstucklex@attglobal.netwrote in message
news:FKudneecv762PYPbnZ2dnUVZ_gydnZ2d@comcast.com. ..
Quote:
Originally Posted by
But the whole point of an iterator is that it has methods you can use to
manipulate it. The PHP internal pointer does not - you can only
manipulate the pointer through the array itself.
>
Additionally, you can define multiple (or no) iterators for the same
list/array/whatever because it is a separate object. But in PHP you
have exactly one pointer which is tied to the array.
>
Thanks Jerry, I get the point now that it's tomorrow.
I was trying to compare apples to oranges, and there was no point.
No sleep, no brain, stupid question.
Thanks for your patience!
Regards,
Vince
|
|
|
What is Bytes?
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 197,014 network members.
Top Community Contributors
|