Skip to content
This repository has been archived by the owner on Jan 8, 2020. It is now read-only.

Bug fix for Zend\Form\Element\Collection::extract() #5220

Closed

Conversation

dhensen
Copy link
Contributor

@dhensen dhensen commented Oct 3, 2013

When a Traversable is encountered it is converted to an array.
By default this is done recursively, so that the Traversable becomes an array representation.
The result of that is saved in $this->object.
In the Collection::extract method when iterating over $this->object there are two branches:

  1. If there is a hydrator, its extract method is called which expects $value as an object.
  2. If $value is an instance of the targetElement, eventualy setObject($value) is called on a fieldset, which also expects an object. Also the targetElement object is set to $value.

In both cases an object is expected, but because of recursive iteratorToArray call it will never be an object.

The fix is to not do it recursively, this way it still gives a key => value array representation of the traversable,
but still gives model objects that can be used by a hydrator or set as targetElement object.

@Maks3w
Copy link
Member

Maks3w commented Oct 3, 2013

Two things:

  • Add a test case
  • That method could be replaced with iterator_to_array native function for this case

When a Traversable is encountered it is converted to an array.
By default this is done recursively, so that the Traversable becomes an array representation.
The result of that is saved in $this->object.
In the Colletion::extract method when iterating over $this->object there are two branches:
1. If there is a hydrator, its extract method is called which expects $value as an object.
2. If $value is an instance of the targetElement, eventualy setObject($value) is called on a fieldset, which also expects an object. Also the targetElement object is set to $value.

In both cases an object is expected, but because of recursive iteratorToArray call it will never be an object.

The fix is to not do it recursively, this way it still gives a key => value array representation of the traversable,
but still gives model objects that can be used by a hydrator or set as targetElement object.

The above problem occurs when an extended Traversable that implements the toArray method is being used in the ArrayUtils::iteratorToArray method.
Because it is recursive per default, it calls the toArray method on the traversable and in case this is implemented in a way that also calls toArray on all child elements, the whole traversable is converted to a scalar-only-array.
So now that there are no object, the Zend\Form\Element\Collection::extract method can not use the hydrator extract method on an array. Also the targetElement hydrator can not do it.
So the extract method fails even though there is probably an array containing a lot of nice values.

The solution chosen by me is to not recursively transform. That works as shown in the two added testcases.
Another fix would be to rewrite the way the extract method works. Or to better dictate how the traversable should be constrained to be transformed in a more controlled way.
@ghost ghost assigned weierophinney Oct 23, 2013
weierophinney added a commit that referenced this pull request Oct 23, 2013
Bug fix for Zend\Form\Element\Collection::extract()

Conflicts:
	tests/ZendTest/Form/Element/CollectionTest.php
weierophinney added a commit that referenced this pull request Oct 23, 2013
- EOF ending
weierophinney added a commit that referenced this pull request Oct 23, 2013
@dhensen
Copy link
Contributor Author

dhensen commented Oct 24, 2013

Thanks for merging into dev. I hope all is good.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants