473,385 Members | 1,356 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

For gurus: bug in php? Recursive foreach dont work properly.

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)
...}
}

Apr 12 '07 #1
13 5389
One more thing: pretend that there is no $nodes[3] = new node(4, 0);
:)

Apr 12 '07 #2
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"
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!
Apr 12 '07 #3
"Toby A Inkster" <us**********@tobyinkster.co.ukwrote in message
news:gr************@ophelia.g5n.co.uk...
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
Apr 12 '07 #4
Vince Morgan kirjoitti:
"Toby A Inkster" <us**********@tobyinkster.co.ukwrote in message
news:gr************@ophelia.g5n.co.uk...
>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"?
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

--
Ra*********@gmail.com

"Wikipedia on vähän niinq internetin raamattu, kukaan ei pohjimmiltaan
usko siihen ja kukaan ei tiedä mikä pitää paikkansa." -- z00ze
Apr 12 '07 #5
Vince Morgan wrote:
"Toby A Inkster" <us**********@tobyinkster.co.ukwrote in message
news:gr************@ophelia.g5n.co.uk...
>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

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.
js*******@attglobal.net
==================
Apr 12 '07 #6
Jerry Stuckle kirjoitti:
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++. :)

--
Ra*********@gmail.com

"Wikipedia on vähän niinq internetin raamattu, kukaan ei pohjimmiltaan
usko siihen ja kukaan ei tiedä mikä pitää paikkansa." -- z00ze
Apr 12 '07 #7
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.

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.
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!
Apr 12 '07 #8
"Vince Morgan" <vi****@REMOVEoptusnet.com.auwrote in message
news:46**********************@news.optusnet.com.au ...
"Toby A Inkster" <us**********@tobyinkster.co.ukwrote in message
news:gr************@ophelia.g5n.co.uk...
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
Apr 12 '07 #9

"Toby A Inkster" <us**********@tobyinkster.co.ukwrote in message
news:iv************@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.
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.
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.
>
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
Apr 12 '07 #10

"Toby A Inkster" <us**********@tobyinkster.co.ukwrote in message
news:iv************@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.

:)
Apr 12 '07 #11
Rami Elomaa wrote:
Jerry Stuckle kirjoitti:
>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.
js*******@attglobal.net
==================
Apr 12 '07 #12
Vince Morgan wrote:
"Vince Morgan" <vi****@REMOVEoptusnet.com.auwrote in message
news:46**********************@news.optusnet.com.au ...
>"Toby A Inkster" <us**********@tobyinkster.co.ukwrote in message
news:gr************@ophelia.g5n.co.uk...
>>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.
js*******@attglobal.net
==================
Apr 12 '07 #13
"Jerry Stuckle" <js*******@attglobal.netwrote in message
news:FK******************************@comcast.com. ..
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
Apr 13 '07 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Dirk McCormick | last post by:
I need to transform something that looks like this <!-- %%%%%%%%%%%%%%%%%%%%%%% --> <MyStructure> <Packages> <Package> <PkgBenefitCode>1</PkgBenefitCode> <PkgBenefitCode>2</PkgBenefitCode>...
4
by: Ryan Ternier | last post by:
I have a section of my project that is Driving me nuts. No one has been able to help that much on it, so i thought of posting it here in hopes someone could help. I need to print out an...
0
by: MrData | last post by:
Hi, I have a big problem with my recursive function. This function have the task to find all blocks in the template file out and put it recursive into a array. hierarchy of the blocks are...
0
by: champ1979 | last post by:
I wrote an algorithm to get all the relatives of a person in a family tree. I'm basically getting all the users from the DB and am doing the recursive logic in code, so that there is only 1 call...
0
by: Silly Milly | last post by:
Calling ALL SSIS GURUS I am trying to import identical MDBs (Access Database) columns into SQL Server 2005 using foreach loop in SSIS. The data and file name of the MDBs are not the same; however...
16
by: colin | last post by:
Hi, is it possible to have a recursive GetEnumerator for traversing a tree structure ? public IEnumerator<DTypeGetEnumerator() { return GetEnumerator(root);
1
by: J. Frank Parnell | last post by:
arrrrrg: Condo for rent has 3 price tiers (for different times of the year): value regular premium For every 7 nites they stay, they get 1 free, and that free one should be the cheapest night...
1
by: rekkufa | last post by:
I am currently building a system for serializing python objects to a readable file-format, as well as creating python objects by parsing the same format. It is more or less complete except for a...
3
by: usman | last post by:
Hi I have a windows service that backups a folder onto another location on the same computer. The service is written in C#. The size of the original folder is large i.e. over 8 GB. Also the...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.