When I was concluding, I realized that the problem was really related to iterator_to_array()
, so I decided to search more deeply in the PHP Documentation / Generators and it shows precisely this type of problem.
Following the documentation:
yield from does not reset the keys. It preserves the keys returned by the Traversable object, or array. Thus some values may share a common key with another yield or yield from, which, upon insertion into an array, will overwrite former values with that key.
A common case where this matters is iterator_to_array() returning a keyed array by default, leading to possibly unexpected results. iterator_to_array() has a second parameter use_keys which can be set to FALSE to collect all the values while ignoring the keys returned by the Generator.
What this means, in general, is that when using yield/yield from, it will outputs keys too (the first yield will be 0
, for instance), just as it actually exists for pure arrays. So the code below will fail similarly (https://3v4l.org/pWeWT):
function willOutputSingle() {
yield 'sameKey' => 'originalValue';
yield 'sameKey' => 'otherValue';
}
var_dump(
iterator_to_array(
willOutputSingle()
)
);
// Outputs: [ 'sameKey' => 'otherValue' ]
It will happen because we yields to pairs like [ 'sameKey' => 'originalValue' ]
and then [ 'sameKey' => 'otherValue' ]
, so when we converts it to array, via iterator_to_array()
the results is basically that:
[ 'sameKey' => 'originalValue',
'sameKey' => 'otherValue ]
But how PHP does not allows identical keys, only the last one is preserved.
The solution to this is pass false
as second argument to iterator_to_array()
, because it will not preserve keys yielded, so result will be an zero-index array. The result will be:
[ 0 => 'originalValue',
1 => 'otherValue' ]