Open ivan-novakov opened 11 years ago
I am not totally sure if i understand it correctly, but can you not pass the correct route/url to the collection in the hydrator (where you embed it in your resource).
So when you add the users
collection to your group/:id
object (in the hydrator) pass a route variable that points to https://server/users/456.
Hope that helps
My case is very similar to the one explained in the docs - Advanced routing. The GET /groups/:id/users
request is routed to the fetchAll
method of the GroupUserResourceController
, so the expected response is a collection:
{
"_links": {
"self": {
"href": "https://server.org/groups/456/users"
}
},
"_embedded": {
"users": [
{
"id": 123,
"name": "Foo Bar",
"_links": {
"self": {
"href": "https://server.org/groups/456/users/123"
}
}
},
]
}
}
The difference from the example in the docs is that the Users
resource is a standalone resource, so I'd like to have the individual collection items' links like https://server.org/users/123
instead of https://server.org/groups/456/users/123
.
In such case the the route for the items in the collection is taken from the controller config (in `$config['phlyrestfully']['resources']) and the metadata are ignored, which seems to me a bit incosistent.
Of course, there are several possible workarounds and also - it's possible that I'm doing something wrong.
Maybe you just have to attach a listener to the createLink
event for this particular route /groups/users
like described here:
https://phlyrestfully.readthedocs.org/en/latest/ref/advanced-routing.html
Like that you can redefine the _links self href? Is that the solution you are looking for?
Yes, this might be a solution, but I thought it could be done in a more elegant way :). The page you are referencing itself says:
"In general, you shouldn’t need to tie into the events listed on this page very often. The recommended way to customize URL generation for resources is to instead use a metadata map."
Thanks for your help anyway.
What goes wrong when you use metadata mapping...? Maybe something is wrong in your mapping definitions? Check whether the classname of the resource you embed corresponds to the classname you use for mapping. I have some similar issues. If the classnames don't match exactly the rendering of the hal resource fails.
Ok, I'll try to be more specific. I have these routes:
'users' => array(
'type' => 'Segment',
'options' => array(
'route' => '/users[/:user_id]',
'defaults' => array(
'controller' => 'PerunWs\UserController'
)
),
),
'groups' => array(
'type' => 'Segment',
'options' => array(
'route' => '/groups[/:group_id]',
'defaults' => array(
'controller' => 'PerunWs\GroupController'
)
),
'may_terminate' => true,
'child_routes' => array(
'group-users' => array(
'type' => 'Segment',
'options' => array(
'route' => '/users[/:user_id]',
'defaults' => array(
'controller' => 'PerunWs\GroupUsersController'
)
)
)
)
)
And these resource controllers:
'PerunWs\UserController' => array(
'identifier_name' => 'user_id',
'listener' => 'PerunWs\UserListener',
'resource_identifiers' => array(
'UserResource'
),
'collection_http_options' => array(
'get'
),
'collection_name' => 'users',
'page_size' => 10,
'resource_http_options' => array(
'get'
),
'route_name' => 'users'
),
'PerunWs\GroupController' => array(
'identifier_name' => 'group_id',
'listener' => 'PerunWs\GroupsListener',
'resource_identifiers' => array(
'GroupsResource'
),
'collection_http_options' => array(
'get',
'post'
),
'collection_name' => 'groups',
'page_size' => 10,
'resource_http_options' => array(
'get',
'patch',
'delete'
),
'route_name' => 'groups'
),
'PerunWs\GroupUsersController' => array(
'identifier_name' => 'user_id',
'listener' => 'PerunWs\GroupUsersListener',
'resource_identifiers' => array(
'GroupUsersResource'
),
'collection_http_options' => array(
'get'
),
'collection_name' => 'users',
'page_size' => 10,
'resource_http_options' => array(
'put',
'delete'
),
'route_name' => 'groups/group-users'
)
Now, the GET /groups/123/users
request is routed to PerunWs\GroupUsersController
, action getList()
. My persistance layer returns a list of users and the resource controller creates a HalCollection and uses the route configured for the controller - groups/group-users
:
https://github.com/phly/PhlyRestfully/blob/master/src/PhlyRestfully/ResourceController.php#L490
This route is used for "self" link generation, which in this case is:
https://server.org/groups/123/users
The problem is that the items of the collection use the same route for generating "self" links, although there exists a valid mapping in the metadata map.
Here it is obvious, that the route name assigned to the HalCollection earlier is used in the "self" link generation of the items:
https://github.com/phly/PhlyRestfully/blob/master/src/PhlyRestfully/Plugin/HalLinks.php#L784 https://github.com/phly/PhlyRestfully/blob/master/src/PhlyRestfully/Plugin/HalLinks.php#L793 https://github.com/phly/PhlyRestfully/blob/master/src/PhlyRestfully/Plugin/HalLinks.php#L839
The metadata map is used only, if an item of the collection contains an embedded resource:
https://github.com/phly/PhlyRestfully/blob/master/src/PhlyRestfully/Plugin/HalLinks.php#L811
It is not used for the "first-level" item itself. And the metadata mapping is OK, because the right hydrator is used and the item is converted to an array properly:
https://github.com/phly/PhlyRestfully/blob/master/src/PhlyRestfully/Plugin/HalLinks.php#L807
The only thing needed is to get the route name from the metadata map along with the right hydrator. Maybe I could prepare a patch to make it more clear.
That's helpful, but please also show me your resource mapping from your config.php :-)
Sure, actually it's here on github :).
It's the InoPerunApi\Entity\Collection\RichMemberCollection
which contains items of type InoPerunApi\Entity\RichMember
:
Suppose we have
users
andgroups
resources with the corresponding routes -/users[/:id]
and/groups[/:id]
.If I need to list users which are members of a group I have to use a "child" resource with a route
/groups/:id/users
, which returns a collection of users.I followed the documentation and everything worked fine. Except one thing - the self links of the users under
/groups/:id/users
were (as expected) using the route from the corresponding resource, for example:Instead, I'd like to have the "standard" location:
I tried to define a
route
option for theUsers
collection in the metadata map, but it was ignored. I examined theextractCollection()
method inPlugin\HalLinks.php
and it seems that metadata are taken into consideration only if the resource is embedded, but not if it is in the "first level" of the collection.I may provide a solution, but I just wanted to ask, if I'm getting this right.