تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Why payload design matters0:00

One of the most important things that we can do when creating an API is designing the payload. That's what I'm going to refer to our response as, because that's what it is, it's our payload. And this is important, of course, because this is an API. Clients are coming to our API to get to our data, so it needs to be structured very well. It also needs to be at least something that the client expects. Like, for example, JSON, which we are returning a JSON structure, but there's a couple of issues here. First of all, we are just taking our model and dumping that into the response. And while there's really technically nothing wrong with doing that in this case, very rarely do we want to just dump our model, because there could be sensitive information. And at the very least, we want to control the structure of it all.

very rarely do we want to just dump our model, because there could be sensitive information. And at the very least, we want to control the structure of it all. And then second, of course, this is JSON. So the convention in JSON is that property names are camel-cased, and that is not the case here. So we want to make quite a few changes here. Now, there is no standard as far as a JSON payload is concerned. So you don't have to adhere to any rules. There is a specification if you want to opt in to use it. It really doesn't matter. You can do whatever you want, because it is your API.

Introducing JSON:API structure1:25

It really doesn't matter. You can do whatever you want, because it is your API. However, this jsonapi.org is a specification that many JSON APIs adhere to. And in fact, we will see some things in Laravel that follow these same ideas. So I think this would be a good thing to follow. We don't have to adhere to these rules line by line, but I think the overall idea is something that we should do. So if we take a look at the specification, what I want to focus on is the document structure. So a document, which would be like an individual object from our model, will have a top level of data.

So a Document, which would be like an individual object from our model, will have a top level of data. And then inside of that data would be everything about that particular Document. So for a Ticket, the data would have the links for that Ticket. If there was any included information, like the author or the user information, that would be inside of included. There's also an attributes somewhere. So the attributes are where we would put the title and the description and things like that. So then the question becomes, how do we take our model and

Creating a Laravel resource2:33

the description and things like that. So then the question becomes, how do we take our model and translate it into something highly structured like this? And the answer is very simple, we use a resource. So we can use php artisan make:resource to make a resource. We want to version this because different versions of our API would have a different resource, and we want to create a TicketResource. And this is going to create a class that has a method called toArray. And that's where we're going to spend the majority of our time, because this is where we essentially design the payload that we want.

And that's where we're going to spend the majority of our time, because this is where we essentially design the payload that we want. And so now that we have this resource, let's go to our TicketController. And for the index route, let's do this. Instead of just returning our tickets, we are going to use our TicketResource. It has a static method called collection. And we can pass in the collection of our tickets in this particular case. And that is going to use the TicketResource to translate our Ticket model into the JSON structure that we are going to design here. So if we go to Postman and we make the request for our tickets,

into the JSON structure that we are going to design here. So if we go to Postman and we make the request for our tickets, we're going to see that there's already a change. First of all, we have this wrapper called data, which that's convenient because, well, we have this data here that will contain our other tickets, so that's nice. And then, of course, we have all of the ticket information as it currently was before. Now, this data is a wrapper, and we can change that. And we'll look at how we can change that in a few moments. But for right now, we're going to leave that as data.

And we'll look at how we can change that in a few moments. But for right now, we're going to leave that as data. And then inside of our controller, let's go down to the show method. And here, we will simply new up the TicketResource. We'll pass in the ticket, and that is going to translate the ticket into our JSON structure. So if we wanted to make another request but for an individual ticket, well, let's do that. Let's add a request. We'll call this getTicket.

Let's add a request. We'll call this getTicket. The URL is going to be practically the same thing, except that we want another segment /one after tickets. We do need the Authorization header, so let's set that to Bearer token. We also want to set the Accept header to application/json. And with that in place, we should be able to make a request for our ticket. And voila, we have our individual ticket data. Once again, we have this data wrapper. So let's take a look at how we could change that if we wanted.

Customizing the data wrapper5:08

Once again, we have this data wrapper. So let's take a look at how we could change that if we wanted. So inside of our TicketResource, we could have a public static wrap. And then we could set this to whatever. So if we wanted our wrapper to be ticket, then we could do that. And whenever we send the request for the individual ticket, we see that the wrapper changed from data to ticket. I don't want to do that, though. I want to adhere to the JSON API specification. So we're going to leave that commented out just so that it's in the code.

Building resource fields5:36

I want to adhere to the JSON API specification. So we're going to leave that commented out just so that it's in the code. But I want our wrapper to be data. And then we just need to start organizing our data in this particular format. So there's this type property, which is required. There's this id that is required as well. And so we can start there. So all we need to do inside of toArray is return an array of our structure. And we'll start with the type. So that was ticket in our case.

And we'll start with the type. So that was ticket in our case. Then we would have the ID, which would be, of course, the ticket ID. And once again, if we just made a request now, we see that our data changes. Now we only see the information that is returned from our resource. So this is how we can start to omit things if we need to omit them from the response. And later on, we'll look at how we can conditionally include or omit things. But this is it. I mean, the concept is very simple. We simply define the things that we want inside of our JSON payload,

I mean, the concept is very simple. We simply define the things that we want inside of our JSON payload, and that's going to be it. So next, we want attributes. And this is where we would have all of the other information about the ticket, such as the title and the description. Although, one thing that I think we will discuss later on is how we can omit the description. Because I don't necessarily think that we need the description for the tickets request.

Because I don't necessarily think that we need the description for the tickets request. Because if we are making a request for all of our tickets, or at least for a collection of tickets, the description isn't necessarily something that the client is going to display, because it could be a sentence, it could be a couple paragraphs, it could be a novel. So we'll look at how we can omit that later on. But for right now, we're going to include the description. Then we also need the status and the createdAt and updatedAt values. The next thing I want to include is a link for the individual ticket.

Then we also need the status and the createdAt and updatedAt values. The next thing I want to include is a link for the individual ticket. That way, the payload will have the link and the client can then use that link to make whatever request that they need for whatever ticket that they need. So let's have links as the next property in our JSON structure. This will be an array where the first object will be self. The idea being that this is the link for this particular ticket. And in which case, we want to call route and our route's name will be tickets.show. And then we just need to supply the ticket, which is the ID. So with that in place, we should be able to now see much more information.

And then we just need to supply the ticket, which is the ID. So with that in place, we should be able to now see much more information. We have our data, we have the type as ticket, ID, the attributes of the ticket followed by the link for that particular ticket. So we're all good there. If we take a look at the collection of tickets, we will see essentially the same things except that now we just have a collection of them. But something else that I want to do for the collection, I don't necessarily want just a straight up collection. I want a paginated collection.

Adding pagination and relationships8:55

I don't necessarily want just a straight up collection. I want a paginated collection. So instead of calling all, let's call paginate. And this is also where we're going to start to see some very JSON API things. For example, we of course have our data here, but there's a links, which is a little bit different, at least as far as the structure is concerned. Then there is a meta property and that's it. So it's not exactly following the JSON API specification. Now, there's one other thing that I want to add. And if we go back to the JSON API specification,

Now, there's one other thing that I want to add. And if we go back to the JSON API specification, we'll see that we can include relationships. So here we can see there's this relationships, and I don't necessarily know where that is defined. Okay, so here's relationships, author, and then the links, and then the data. So it's essentially the same kind of structure that we did for the ticket except that it's more specific for the user, which that's easy enough to do. So let's add the relationships, which is going to be an array, where we will have the author and the data for

So let's add the relationships, which is going to be an array, where we will have the author and the data for the author is what we already have available to us, at least as far as the userId is concerned. So the type here is going to be user. Then we will have the ID, which will come from the userId attribute from our model. We could also include some links here, but we don't have a route set up for our users yet. So what I want to do then is we'll still have the self, but

we don't have a route set up for our User yet. So what I want to do then is we'll still have the self, but I'm going to add just to do. So with that in place, we should be able to go back. And whenever we make a request, let's do for the individual ticket. We should see the relationships. We have the author, where the data is of type User, the ID is one. And then we have the links, which we will implement at a later time. So there we have our JSON structure. I'm not going to say it's perfect, but

So there we have our JSON structure. I'm not going to say it's perfect, but I think that it's much better than what we had before, if a little verbose. But it at least provides all of the pertinent information to the client in a structured manner. In the next episode, we will look at how we can conditionally include or omit data from our resource.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟