willdurand / Hateoas

A PHP library to support implementing representations for HATEOAS REST web services.
https://williamdurand.fr/Hateoas/
Other
1.04k stars 118 forks source link

[RFC] Force link relations to an array for HAL #199

Open saracen opened 9 years ago

saracen commented 9 years ago

There's a note in the HAL specification located at http://stateless.co/hal_specification.html:

Note: If you're unsure whether the link should be singular, assume it will be multiple. If you pick singular and find you need to change it, you will need to create a new link relation or face breaking existing clients.

At the moment, serializeLinks and serializeEmbeddeds only serialize links/items to an array when there is more than one. With the application I'm working on it makes sense to force certain relations to always be an array (for example: a user can have many role relationships, but sometimes might only have one role).

It doesn't appear there's a way to currently do this, or easily do it without either passing some kind of configuration information into the serializeLinks/serializeEmbeddeds methods, or attach it to Model\Link and Model\Embedded classes.

I'm happy to implement this if you can provide some direction as to how you'd want it to look. My preference at the moment would be to maybe change the constructor for Link and Embedded to include an array $options that we can populate with configurables that the serializers can use.

adrienbrault commented 9 years ago

It is also better to return an empty array when there is no links.

I am not really sure how to address the issue, given that some links are added at runtime

saracen commented 9 years ago

Would you not be happy if we converted the relations to an array as soon as we got any Relation that said it was an array item? This would mean that adding a relation at runtime as an array item would convert the serialized representation to an array.

Empty arrays would be possible, but the restriction of a relation requiring an embedded or a href would have to be removed.

jean-gui commented 9 years ago

:+1:. I believe there's the same issue with CollectionRepresentation/PaginatedRepresentation (probably because they also create relations).

saracen commented 9 years ago

I solved this for our own requirements in our codebase by extending the JsonHalSerializer class and checking whether the relationship name contains "[]" at the end.

This requires modification to all other serializers being used though (For example, the XML serializer needs to remove the "[]" from the relationship name). It also doesn't advertise empty arrays when no links are provided.

Example:

        foreach ($this->membership->getRoles()->toArray() as $role) {
            $relations[] = new \Hateoas\Configuration\Relation(
                'role[]',
                new \Hateoas\Configuration\Route(
                    'get_sitemembershiprole',
                    [ 'role' => $role->getId() ]
                ),
                new \Hateoas\Configuration\Embedded(
                    new SiteMembershipRoleResponse($role)
                )
            );
        }

A hacky solution though :(

vortechs2000 commented 7 years ago

I'm running into this too - sometimes the relation only has a single entry, and then we get an object, but it's a link that has the capacity for multiple entries. This means our callers need to check which it is and handle both cases. That doesn't seem right.