-
-
Notifications
You must be signed in to change notification settings - Fork 838
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix : normalize collection #335
Conversation
Don't forget to create a PR on the 1.0 branch |
@@ -152,7 +152,7 @@ public function normalize($object, $format = null, array $context = []) | |||
$subResource = $this->resourceResolver->getResourceFromType($collectionType) | |||
) { | |||
$values = []; | |||
foreach ($attributeValue as $index => $obj) { | |||
foreach ($attributeValue->getValues() as $index => $obj) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've maybe missed something but how can you be sure that the getValues()
method exists? Isn't it something specific to Doctrine?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getValues method is from Collection interface of symfony. So every collection on symfony have it. It prevent the issue that array collection internal array can be not ordered properly.
If you want we can add :
$values = $attributeValue instanceof Collection ? $attributeValue->getValues() : $attributeValue;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK there is no Collection
interface in Symfony. Only in Doctrine collection. And this serializer can be used with other kind of \Traversable
such as plain old arrays.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same concern here, we're not always using Doctrine Collections ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could use Doctrine's Collection
interface as it's in doctrine/common
and it not related/dependent at all on any database-related stuff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$values = $attributeValue instanceof \Traversable ? iterator_to_array($attributeValue, false) : array_values($attributeValue);
Can't you fix your entity getter instead (to add the |
How do we do when we actually want to use hashmaps? In my case I don't really care as I've never had to use it with DunglasApiBundle, but it would be an issue to completely prevent this use case IMO. |
@theofidry you're right ! I have an issue now with a relation that is indexed with a string so a hashmap .... So this simple fix can't works ... In https://github.com/dunglas/php-property-info/blob/master/src/PropertyInfo/Type.php you can identify a collection, but no difference between hash // array. What do you think ? |
@dunglas @theofidry What do you think about @MLKiiwy question ? |
PHP Property Info is deprecated and has been merged into Symfony as the Symfony PropertyInfo Component. I don't think that this is the responsibility of this component to handle such differences. What about just having smart getter and setters updating array correctly? |
Well, I would say he's suggestion makes sense but would still be tricky because you can still use an hashmap with int values :/ The best thing IMO is to either reset the keys in the array setter (or remover if you have one) or return all the values in the getter (but likely more costly performance wise): public function setMyArray(array $arr)
{
$this->myArray = array_values($arr);
}
public function addToMyArray($val)
{
$this->myArray[] = $val;
}
public function removeFromMyArray($val)
{
$key = array_search($val, $this->myArray, true);
if (false === $key) {
return;
}
if (0 === $key) {
array_shift($this->myArray);
return;
}
unset($this->myArray[$key]);
$this->myArray = array_values($this->myArray);
} |
@MLKiiwy any news about this PR? |
As I've mentioned in #285 (comment) it's not a "Doctrine edge case". If we know it's a to-many relation we should normalize it to numerically-indexed non-sparse array.
For a relation? You mean like with Doctrine's "indexBy" option? I'd think that's a responsibility of the mapping metadata layer to provide such information... |
Fixed in 2.0. |
How was this fixed? |
Maybe I closed to quickly. |
I'm closing this one, need to test in 2.0 if the issue is still here |
In certain case collection are normalize into object (json_encode transform array( 1 => 'A' ) into { '1' : 'a' } instead of ['a'].
Here is the bug fix with the corresponding scenario failing on master.