Closed weaverryan closed 10 years ago
/places?embed=checkins,merchant,current_opp.images
? It seems very flexible for the client. And if we use this, is this reasonably possible with the serializer?There is no preferred answer about the plural vs singular question. What matters the most is to be consistent.
A) If the client sends extra properties (or perhaps a property that exists in the representation, but is unmutable), is it better just to ignore these properties or return a validation error?
I'd say it depends. Do we want to be "strict" or pragmatic?
B) What do you think about allowing the client to specify which embedded resources they want - e.g. /places?embed=checkins,merchant,current_opp.images? It seems very flexible for the client. And if we use this, is this reasonably possible with the serializer?
OData to the rescue! A good read from François: http://redotheweb.com/2012/08/09/how-to-design-rest-apis-for-mobile.html.
C) Have you seen https://github.com/thephpleague/fractal? I'm not sure its mature or flexible enough, but I did like how explicit it was to create your representations, especially if your representations begin to differ from your model (instead of using VirtualProperty's etc). Just wanted to see if you had any strong thoughts one way or another :).
Yeah, and I don't really like this package, sorry. I don't like the way representations are created, and I don't think it is worth using it.
OData to the rescue! A good read from François: http://redotheweb.com/2012/08/09/how-to-design-rest-apis-for-mobile.html.
Oh, so this idea of ?expand=
is already a semi-standard, which appears to "work" exactly like embed
in the URL I was giving. That's awesome. Now, is this easily possible with the serializer? Without manually giving each "expandable" relationship property its own group? Or is that exactly what we should do.
I think we should have a whitelist of known relationship properties.
ConstraintViolationList
down to a very simple structure (only showing 1 error per field, even if there is more). My Api Problem response looks like this:{
"type": "http://someUrl.com/errorCodes#ErrorCode",
"title": "Human readable description",
"errors": {
"firstName": "Please enter a name"
}
}
Do you see any issues? Also, it seems that you might prefer vnd.error
?
Thanks!
D) I'm using Symfony's validator component, though I don't really want to focus on this [...]
I'm fine with your API Problem response. vnd.error
is not really self-explaining.
E) For 404, 403 and 500 errors, we'll need an ExceptionListener that transforms these into the proper "Api Problem" JSON structure. [...]
Yeah, it is better. You can use a basic middleware in Silex. It is not difficult, and I think people will understand it.
F) Can you take a quick glance at the Programmer controller so far and see if you spot any horrible things? :)
Ok, quickly read it, and it looks good to me. Will do an extensive review tomorrow.
BTW, I don't get email notifications from GitHub...
Next!
ApiProblem
inside of it. I also have a simple listener to convert all of this into a response. The listener also tries to convert non-ApiProblemExceptions (anything under /api
) to JSON as well (btw, we're not concerned yet about multiple response formats). But in this case, finding a decent "type" for the API problem is awkward - all I really want to communicate is the status code (e.g. 404). I'm just using the status code as the "type" right now, but it doesn't seem quite right. Besides, the "code" should be a URL. Any thoughts about this setup? What should the "code" be for things like 404 and 403 exceptions?/api/
prefix, whereas the rest of the site is not under this prefix (e.g. /api/programmers
versus /programmers
). I thought that trying to use one controller to serve both the website and the API would involve too much complexity. And besides, if you're building things nicely, you can avoid code duplication (other than some boilerplate controller code). Thoughts?If it is awkward, then don't use a custom type, application/json
is fine for errors. I would not create my own type here. However, I don't get the "code" stuff.
Let's keep everything simple: an error response is made a message for the end-user, and optionally a message for the developer. Most of the time, API error reponses are either not accurate or dumb. According to Apigility guys, if I remember correctly, we must return the right HTTP status code (which already means a lot, facebook does not do that for instance...), a message for the end-user (which should be translated so that clients could use it directly), a link to the error explanation for the developer or, at least, a message for the developer (in English), in other words, something meaningful for the developer.
Yes, PATCH is hard to use (well, tedious). So, either we don't use it (:+1:) or we explain it the right way, not the wrong way. For a small flag, I would rather expose it as a subresource:
/api/programmers/1/angry
(yes/no)
For I, I like the FOSRestBundle way actually, one action = one resource (or collection), no matter the format you serve to represent it. Using two controllers, you basically break this, as you distinguish HTML and JSON/XML. However, these are formats, and resources should not depend upon them. Is it understandable?
F) Can you take a quick glance at the Programmer controller so far and see if you spot any horrible things? :) https://github.com/knpuniversity/rest/blob/finish/src/KnpU/CodeBattle/Controller/Api/ProgrammerController.php. This is only done through ch7 (well, ch7 is not fully done) - so we're looking at a basic CRUD API without any idea of linking or using any outside libraries to help us serialize, etc.
I don't really like the updateProgrammerFromRequest()
method, but apart from that I'm fine with the code. For instance, in newAction()
I expect a programmer to be created, not "updated from the request". It makes the code less readable, and less self-explanatory.
Yea, awesome! Now things are getting hard, as I expected! More questions :) - or follow-ups from above:
/api/programmers/1/angry
- the Content-Type
of the request would actually be text/plain
, correct?updateProgrammerFromRequest
to handleRequest
. Is there anything else we can change to make this better? Obviously, I'm using this function because there's a lot of logic that the "new" and "update" both need :).J) well, it can be form-urlencoded
too:
value=true|false
or simply:
true|false
K) exposing sub-resources sounds better to me, but if you really really want to use PATCH, feel free.
L) 2 URIs for each resource is wrong to me.
L) 2 URIs for each resource is wrong to me.
This is tough :). It means then that we must introduce a view layer and use one controller for everything. I think that's quite complex. And again, something like GitHub does this:
Does using a different subdomain make the difference? Because then it's technically 2 different applications (and hey, maybe the HTML version is using the API behind the scenes to get data)? Thoughts?
... update ... the more I think about it, the more I think we should mention this issue earlier, and then perhaps show how to fix it later. It's a cool point because we can say "why just return JSON and XML? If you do a good job, this URL can return HTML too, using most of the same code".
I have a long answer but it is late here, and I just can't think about anything anymore at the moment. Let's not change anything by now. More to come tomorrow :sleeping:
I don't think it is complex to serve either HTML and JSON using the same controller. That is why I expect from my students for example. IMO, one of the main benefits is that it makes the transition to Symfony/FOSRestBundle smoother/easier.
Does using a different subdomain make the difference? Because then it's technically 2 different applications
Probably, then it makes sense to have different urls.
Here, we build an API (a REST-ish one), and a single app, hence the idea of not duplicating the code. Maybe we can explain our choice to separate the API part than the HTML/Website part, but what are the pros/cons?
Ok cool :). So I think I'd like to unify HTML with JSON later in the tutorial. Early-on, there are just a few pieces we're missing, like content-negotiation and needing a layer to gather the information from the request body or from the POST variables. But once we've laid out the foundation, it seems very cool to me to basically say "look, JSON and HTML aren't really different, let's see how easy it will be to unify things now".
Early-on, I think we should make these changes:
rest-basics
: Under Resources and Representations
, add in some details about how HTML is just another representation, just like JSON and XML. And how an "API" as we call it, could just be your application, where you return HTML and JSON from the same URL and from the same code.post
: Under First Endpoint: POST /api/programmers
we'll talk about the initial decision to build the API under a different URL than the rest of the app and with a different route and controller. We can say that we're doing this for simplicity initially, but it doesn't need to be this way. And that later, we'll look at how HTML and JSON could be served from the same URL.What do you think? :)
Tip top! :+1:
Is everything ok on your side?
@willdurand Yes, sorry for the silence ! Big travels, then when we got back, we still had plenty to work on! We've recorded a bunch of chapters now, and now I need to turn a few more chapters into rough copies for your review. I think we will then be nearing finishing episode 1. I'll ping you this week or next with a few more things to review. I'll open up a new issue with each question (hence closing this).
Thanks for checking in :)
Alright! :heart_eyes:
My own notes of things to not forget about or revisit as I create the project for this tutorial:
/programmers/...
versus/programmer
- I can't remember which is "preferred"