Skip to content
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

Closed
wants to merge 1 commit into from
Closed

Fix : normalize collection #335

wants to merge 1 commit into from

Conversation

MLKiiwy
Copy link
Contributor

@MLKiiwy MLKiiwy commented Nov 18, 2015

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.

@vincentchalamon
Copy link
Contributor

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) {
Copy link
Member

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?

Copy link
Contributor Author

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;

Copy link
Member

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.

Copy link
Contributor

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 ;)

Copy link
Contributor

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.

Copy link
Contributor

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);

@dunglas
Copy link
Member

dunglas commented Nov 18, 2015

Can't you fix your entity getter instead (to add the getValues() call)? If I understand well how it works it add a hard dependency to Doctrine Collections to (IMO) fix a Doctrine bug/edge case.

@theofidry
Copy link
Contributor

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.

@MLKiiwy
Copy link
Contributor Author

MLKiiwy commented Nov 19, 2015

@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 ...
@dunglas I suggest to modifiy the vendor php-property-info because the issue is to identify hash and arrays. In php hash == array but in json hash == object and array == array.

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.
If we add a difference : isHash() for exemple => we can modify DoctrineExtractor to identify relation indexed by string.

What do you think ?

@vincentchalamon
Copy link
Contributor

@dunglas @theofidry What do you think about @MLKiiwy question ?

@dunglas
Copy link
Member

dunglas commented Dec 14, 2015

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?

@theofidry
Copy link
Contributor

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);
}

@sroze
Copy link
Contributor

sroze commented Dec 18, 2015

@MLKiiwy any news about this PR?

@teohhanhui
Copy link
Contributor

@dunglas

Can't you fix your entity getter instead (to add the getValues() call)? If I understand well how it works it add a hard dependency to Doctrine Collections to (IMO) fix a Doctrine bug/edge case.

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.

@theofidry

How do we do when we actually want to use hashmaps?

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...

@dunglas
Copy link
Member

dunglas commented Aug 19, 2016

Fixed in 2.0.

@dunglas dunglas closed this Aug 19, 2016
@teohhanhui
Copy link
Contributor

How was this fixed?

@dunglas
Copy link
Member

dunglas commented Sep 1, 2016

Maybe I closed to quickly.

@dunglas dunglas reopened this Sep 1, 2016
@MLKiiwy
Copy link
Contributor Author

MLKiiwy commented Jul 17, 2017

I'm closing this one, need to test in 2.0 if the issue is still here

@MLKiiwy MLKiiwy closed this Jul 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants