php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #38618 default implementation of hasChildren() in RecursiveArrayIterator does not work
Submitted: 2006-08-27 22:10 UTC Modified: 2008-05-15 23:23 UTC
From: mike at silverorange dot com Assigned: colder (profile)
Status: No Feedback Package: SPL related
PHP Version: 5.2.5 OS: *
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: mike at silverorange dot com
New email:
PHP Version: OS:

 

 [2006-08-27 22:10 UTC] mike at silverorange dot com
Description:
------------
The default implementation of hasChildren() in RecursiveArrayIterator does not work if the recursive array contains object references. If I subclass the RecursiveArrayIterator and re-implement the method exactly as it is in the source code everything is fine. If I use the default implementation, the objects in my array do not get iterated.

Inside my re-implemented hasChildren() method if I call parent::hasChildren() it returns 1 when $this->current() is an object.

Reproduce code:
---------------
Code to reproduce:

http://wiki.silverorange.com/Recursive_Array_Iterator

Expected result:
----------------
Expected output from reproduce code:

Default recursive array iteraration:
1 => apple
2 => orange
3 => banana
1 => grape
2 => peach
3 => strawberry
4 => grapefruit

Reimplemented hasChildren() recursive array iteraration:
1 => apple
2 => orange
3 => banana
1 => grape
2 => peach
3 => strawberry
4 => grapefruit

Default recursive array iteraration:
1 => apple
2 => orange
3 => banana
1 => grape
2 => peach
3 => strawberry
4 => grapefruit

Reimplemented hasChildren() recursive array iteraration:
1 => apple
2 => orange
3 => banana
1 => grape
2 => peach
3 => strawberry
4 => grapefruit


Actual result:
--------------
Output from reproduce code:

Default recursive array iteraration:
1 => apple
2 => orange
3 => banana
1 => grape
2 => peach
3 => strawberry
4 => grapefruit

Reimplemented hasChildren() recursive array iteraration:
1 => apple
2 => orange
3 => banana
1 => grape
2 => peach
3 => strawberry
4 => grapefruit

Default recursive array iteraration:

Reimplemented hasChildren() recursive array iteraration:
1 => apple
2 => orange
3 => banana
1 => grape
2 => peach
3 => strawberry
4 => grapefruit


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-06-28 01:51 UTC] mike at silverorange dot com
This bug still exists in PHP 5.2.3 using the same test script as before.
 [2007-07-02 15:03 UTC] mike at silverorange dot com
Sorray about that. Try this link:

http://labs.silverorange.com/local/solabs/include/recursive-array-iterator.txt
 [2007-08-20 10:34 UTC] jani@php.net
Replace "protected" with "public" and it works fine..
 [2007-08-20 14:05 UTC] mike at silverorange dot com
I tried changing the scope of the $title property from protected to public and the test case does indeed run correctly.

Even so, the test case should still run correctly when the property is protected.
 [2007-08-20 14:14 UTC] mike at silverorange dot com
I played around with the test case a bit more and it seems that the default RecursiveArrayIterator iterates the public properties of objects within the arrays.

For example, if I adda public $foo = 'bar' property to the Fruit class, I get the following (incorrect) output:

Default recursive array iteraration:
title => apple
foo => bar
title => orange
foo => bar
title => banana
foo => bar
title => grape
foo => bar
title => peach
foo => bar
title => strawberry
foo => bar
title => grapefruit
foo => bar
 [2007-08-20 15:01 UTC] jani@php.net
Marcus, can you check this out please?
 [2007-12-05 16:00 UTC] helly@php.net
So far the behavior is expected as ArrayObject/ArrayIterator follow arrays as well as objects. For 5.3 I added a new flag ArrayObject::CHILD_ARRAYS_ONLY that can be used to prevent ArrayIterator from following objects. IF you feel this is ok let me know. If you think the behavior should be reverse, meaning the flag should be active by default and there should be a way to disable it then open a RFC on internals@php.net.
 [2008-05-15 23:23 UTC] colder@php.net
I MFB'ed that patch to HEAD as well with a slight distinction,
The constant now belongs to RecursiveArrayIterator, and not ArrayObject anymore.

This flag is off by default.
 [2010-05-20 12:48 UTC] mi dot olszewski at gmail dot com
Hi,

I've stumbled upon this issue and although fix (RecursiveArrayIterator::CHILD_ARRAYS_ONLY flag/constant) is available on PHP 5.3 it is not present in PHP 5.2.

Additionally PHP sources are out of sync - the new constant is present only in spl_array.c file but recursivearrayiterator.inc is not updated: the CHILD_ARRAYS_ONLY constant is missing and hasChildren() definition contains only is_array() check. This is really confusing because new users of RecursiveArrayIterator will check PHP sources first. It took me quite a while to find out about this new flag. Also - most of hosting providers still use PHP 5.2 which means most of people will have to use hasChildren() override workaround to get it working.

Could you please add the constant to PHP 5.2 branch and update recursivearrayiterator.inc (and documentation at http://www.php.net/~helly/php/ext/spl if possible)?

Thank you.
 [2017-02-21 10:46 UTC] tularis@php.net
Automatic comment from SVN on behalf of tularis
Revision: http://svn.php.net/viewvc/?view=revision&revision=341941
Log: Add simple documentation for the CHILD_ARRAYS_ONLY flag for RecursiveArrayIterator that was added as a fix to Bug #38618 back in the 5.3.0 release.

Provided by John Flatness (john@zerocrates.org)
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC