12.
The HAL JSON Standard
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
Whoops, an error! Please, try again later.
11 Comments
If I understand correctly, using Hateoas annotations no longer requires parameter resolution in LinkSerializationSubscriber::onPostSerialize()?
I used the LinkSerializationSubscriber::onPostSerialize() method to dynamically inject some parameters from the current Request, using $this->request->getCurrentRequest() into your @Link, but don't know how to do the same for @Hateoas\Relation. How can I dynamically inject some parameters (from the current Request) into a Hateoas annotation before it processes/resolves its parameters?
I tried doing an elseif ($annotation instanceof Hateoas\Relation) { and inject them there, but this doesn't work, probably because the $this->annotationReader->getClassAnnotations returns a copy of annotations, and not their references which can be modified prior to processing.
Thank you!
Hey Vlad!
You're absolutely right - LinkSerializationSubscriber is no longer needed. Were you passing some extra request information into the expression before? What exactly were you doing? The Hateoas library *tries* to give you access to everything you'd need. There's even a few more things that the bundle gives you access to: https://github.com/willdura...
But let me know, and we'll find a solution :)
Cheers!
Hi Ryan!
Yes, I'm trying to get a specific parameter from the Request object. In my case the route is: /api/schools/{schoolId}. The `schoolId` parameter is needed to build the links (_self, next, previous) in the `_links` section. With LinkSerializationSubscriber I was able to get the current Request ($this->request->getCurrentRequest()) in the onPostSerialize() method and extract the `schoolId` from it, but since Hateoas bypasses LinkSerializationSubscriber, I'm not sure how to do it there.
You've already shown me how to get the current request from a controller or a service, but I don't know how to get it from a Hateoas annotation.
Thank you for your reply.
Hey Vlad!
Ok, great! So, the first question is: inside what entity/class are you adding this annotation? If, for example, you are inside of the School entity, then you can use the expression language to get the schoolId value without doing any extra work. It would look something like this:
So, you don't really need to fetch this schoolId from the request directly. Ultimately, you are serializing an object, and when you do that, it is highly likely that the value you need - the school id - is contained inside of that object somewhere (and so you can fetch it with the expression).
Let me know if this makes sense!
Hi Ryan,
Unfortunately, this isn't just for the School entity, but for pretty much all exposed entities, since my end point URLs depend upon the schoolId parameter: /api/schools/{schoolId}, /api/schools/{schoolId}/students, /api/schools/{schoolId}/faculty, etc.
Inside controllers' actions I'm able to get the schoolId from the Request parameter, like you've explained in the tutorial.
Thank you!
Hi Vlad!
Hmm, I would still expect each object that's being serialized to ultimately have a relation back to the School object somehow (e.g. the Faculty would have a ManyToOne with School, so you could do something like object.getSchool().getId() in the expression). But, let's suppose that's not true, and we need to do it this other way :). A few suggestions:
1) Based on what I just saw in the code, you have a container variable in the expressions. It's ugly, but you could do `container.get('request_stack').getCurrentRequest().attributes.get('schoolId')
2) You can add a custom function to the expression (e.g. getSchoolId()) that does whatever you want. Just create a service and tag it with hateoas.expression_function. As far as I can see, this is an undocumented feature (it's quite advanced). Here is the code that handles it: https://github.com/willdura...
As you can see, for (2), your class must implement am ExpressionFunctionInterface.
I hope this helps!
Hi Ryan!
Thanks to the HATEOAS samples and your wonderful suggestions, I was able to get it to work!
This is great! I'm really excited.
I'll paste in my code here, in case anyone else decides to do something similar:
<strong>SchoolExpressionFunction.php</strong>
Register as a service in <strong>services.yml</strong>
Use in Hateoas annotations (e.g. <strong>Student</strong> entity)
My setup is a bit different, as I have entities split in two different databases, hence it wasn't easy to get the school ID for some entities using relationships.
Thank you again for your help, I really appreciate it!
Awesome work - congrats!
Hi Ryan,
I posted a comment here yesterday to let you know I got it work, as well as code samples for others interested in the same thing, but the comment was marked as pending for review. I don't know if you need to approve it first.
Thank you!
Hey, Vlad!
Sorry, looks like this comment somehow didn't pass Disqus spam filter. I've just approved it!
Thanks for let us know.
Cheers!
Thank you, Victor!
"Houston: no signs of life"
Start the conversation!