ZF-6995: Zend_config : toArray conflict with iterator implements.

Issue Type: Bug Created: 2009-06-12T02:41:50.000+0000 Last Updated: 2009-06-16T12:20:59.000+0000 Status: Resolved Fix version(s): - 1.8.4 (23/Jun/09)

Reporter: CHOTIN Nicolas (nicochot) Assignee: julien PAULI (doctorrock83) Tags: - Zend_Config

Related issues: Attachments:


Function "toArray()" is created with a foreach on "_data". Interface "iterator" is implemented with : "next($this->_data)" and others functions of iterator directly on "_data".

My problem is function "toArray()" which is in conflict with the iterator interface. For fix that , we must create a clone of object and after we can use "toArray()".

But function "toArray()" should be NOT in conflict with iterator ?

For me, the problem is not "toArray()" but the implement of "Iterator". And is just when we want used "toArray()" AND iterator in same time on same object.

This problem could be apply to all classes with iterator and "toArray()". But I don't know if it's a usage problem or a bug.

Nicolas CHOTIN.


Posted by Rob Allen (rob) on 2009-06-12T06:59:39.000+0000

Would you mind providing the code you're using along with the results you're getting and the results you are expecting?



Posted by julien PAULI (doctorrock83) on 2009-06-12T11:07:49.000+0000

Foreach() uses the array directly and thus, the internal array iterator and not Zend_Config's iterator.

Could you provide a use case ?

Posted by Tomoaki Kosugi (noopable) on 2009-06-13T01:08:54.000+0000

Hi I was put in a similar situation. toArray breaks iteration. At between before and after toArray, a behavior of valid and current is amusing.

Here is repro-code

<pre class="highlight">
$config = new Zend_Config(array(1,2,3));

var_dump($config->valid());  // true
var_dump($config->current()); // int(1)

$dummy = $config->toArray();
var_dump($config->valid()); // true
var_dump($config->current()); // false

2nd sample should be " not valid " or "valid? int(1)"

One Solution is clone $this->_data before "foreach($this->_data" In Zend_Config::toArray() .

Posted by CHOTIN Nicolas (nicochot) on 2009-06-15T07:38:48.000+0000

In my case it's a controller for testing. I have create a config file with a "value" for config and a "value" for testing :

test.c1.regexp = ^/index/test test.c1.test = /index/test test.c2.regexp = ^/index/test1 test.c2.test = /index/test1

The initialization of object is in loop of tests, because this object is initialized only when used. But in real context we don't have a loop on same object "Zend_Config".

So for me it's a usage problem but it's interesting to add a warning in documentation mostly if Zend_Config it's not alone class in this case.

Posted by julien PAULI (doctorrock83) on 2009-06-15T09:25:43.000+0000

Ok I see.

toArray() works directly on the _data array, and so does the iterator. When calling toArray(), a foreach loop is used to iterate throught _data, that foreach loop first calls rewind() internaly , and then iterates. The problem is that the foreach loop leaves the array iterator at an undefinied position (that's why rewind() is called by foreach before the iteration). Then when you call current() on your object, it just says it doesn't have a current value.

<pre class="highlight">
$config = new Zend_Config(array(1,2,3));
$config->rewind(); // rewound
$config->toArray(); // the internal iterator is somewhere after the last position due to foreach loop
assert($config->current() == false); // OK

To see that, create a getIndex() method in Zend_Config, which return $_index; and try this :

<pre class="highlight">
$config = new Zend_Config(array(1,2,3));
$config->rewind(); // rewound
$config->toArray(); // the internal iterator is somewhere after the last position due to foreach loop
assert($config->key() == $config->getIndex()); // WRONG , $config->key() returns NULL while getIndex() has the right value

The patch is easy, trigger the internal PHP copy-on-write system to make foreach loop over a copy of the _data array, and not the real _data. Just add :

<pre class="highlight">
public function toArray()
        $array = array();
+      $data = $this->_data;
        foreach ($this->_data as $key => $value) {
            if ($value instanceof Zend_Config) {
                $array[$key] = $value->toArray();
            } else {
                $array[$key] = $value;
        return $array;

Even not using the new $data variable created, it increments the internal refcount on the _data structure, making foreach use a copy of it ;-)

Posted by Rob Allen (rob) on 2009-06-16T02:10:12.000+0000


Fancy writing a unit test and then patching?



Posted by julien PAULI (doctorrock83) on 2009-06-16T04:07:50.000+0000

I'm on it

Posted by julien PAULI (doctorrock83) on 2009-06-16T12:20:57.000+0000

Fixed in SVN r16090

Have you found an issue?

See the Overview section for more details.


© 2006-2018 by Zend, a Rogue Wave Company. Made with by awesome contributors.

This website is built using zend-expressive and it runs on PHP 7.