در حال بارگذاری ...

Introducing Resource Classes0:00

Next up, we have resource classes, which is brand new in Laravel 5.5. So you'll find that you have a new command called make:resource. And you can think of a resource class as sort of like a transformer. It will take an Eloquent model and transform its data structure into the proper type and the proper set that can then be returned and cast to JSON. So let's give this a shot. Let's make a resource for a User. Okay, so now you'll see by default this is going to place that within your app/Http/Resources directory here. Now, in terms of naming convention, if you want to call this class UserResource or user,

HTTP resources directory here. Now, in terms of naming convention, if you want to call this class UserResource or User, it doesn't really matter. It's entirely up to you. Now, you'll see that by default, our toArray method simply delegates to the toArray method on your Eloquent model. So let's just give this a shot. In my routes file, when we request the home page, I'm going to say, give me the very first User. Now, note there's no resource being used here.

Default JSON vs Control0:53

give me the very first User. Now, note there's no resource being used here. But anyways, if we give this a run, yeah. Okay, so we have our model and it has been properly cast to JSON. And in many situations, this is exactly what you want. And what you could even do, if it makes sense, is override the toArray method on your model if you need to control specifically what gets returned when it is cast to JSON or to an array. So in this case, you can see we overwrote that. So like I said, in many situations, this is all you really need, especially if you're building an API that you, the project owner, will consume and nobody else.

So like I said, in many situations, this is all you really need, especially if you're building an API that you, the project owner, will consume and nobody else. In those situations, you can be a little more flexible because you're in control of everything. However, in other situations where you're creating an API that will be exposed to potentially millions of people, you need to be a little more strict. You can't just change column names willy-nilly and expect everyone to update their API calls to reference the new property names that you changed to. So yeah, let's see a modified version now. We're going to use our User resource. So right at the top, let's say User and import this.

Customizing Resource Output1:54

We're going to use our User resource. So right at the top, let's say User and import this. But we have two Users, so let's just say as User resource. All right. So now I'm going to wrap this within a User resource. And in fact, why don't we extract this just to make it a little more clear. Okay, now if we switch back to Chrome and give this a refresh, we have more or less what we had before. But you can see Laravel is using kind of a generic, simple data structure here, where we have a data object that contains your fields.

But you can see Laravel is using kind of a generic, simple data structure here, where we have a data object that contains your fields. Now, we can switch over there and modify this however we need to. So maybe I only want to expose the name. And notice in this case, the key, those will be the values that the user references. But now because we do it this way, the key doesn't have to match up specifically with the column name in your table. And that can be useful, and it does give you more flexibility down the line if things change and your table structure changes. Anyways, let's just stick with these two.

if things change and your table structure changes. Anyways, let's just stick with these two. And if we give this a refresh, yeah, now we're only exposing these two columns to the user. However, what if you're conforming to a spec, and you do need other fields in your response? Like maybe you're conforming to JSON. That's a very simple spec where we wrap our data within this object. And then you might also have a status property. In those cases, you can use the with. So we'll accept the request.

In those cases, you can use the with. So we'll accept the request. And then here, yeah, basically anything we return will be a sibling of data, as you can see there. So in this case, yeah, maybe you want to set status to success or determine that. Whatever you need to do there, this makes it really easy. And you define it in exactly one place, so that now throughout all of your controllers, you're not having to reproduce this data structure for every single response. Like, you know, if we had a PostController here,

you're not having to reproduce this data structure for every single response. Like, you know, if we had a PostsController here, well, maybe you get all of your posts, but that needs to be returned in the proper format. So maybe if you were doing it generically, you would do something along the lines of this. And then you'd have status, success. Yeah, something like that. Well, now if you want, that can all be stored within your transformer or in your resource class.

Handling Relationships Safely4:06

Well, now if you want, that can all be stored within your transformer or in your resource class. And that'll still work, makes things a bit more reusable and a bit more dry. Now let's clear this up. What about the situations when you have relationships? So like maybe as part of the User, I want to include the profile. So I could say $this->profile. But now you might be wondering, well, I'm referencing properties and methods on my main User class, but we're within a UserResource class.

well, I'm referencing properties and methods on my main User class, but we're within a UserResource class. Now, a neat thing to recognize is that on the class, so this is your resource class that all of your sub-resources extend. Anyways, they use a trait here called DelegatesToResource. So yeah, this is just a nice, simple trait that will take, if we scroll down, any dynamic property access or method calls, and it's going to delegate to the underlying resource. And in this case, the resource property, that would refer to your User model or whatever the associated model happens to be.

And in this case, the resource property, that would refer to your User model or whatever the associated model happens to be. So that gives you the ability to keep it nice and simple. And you're not having to say things like this model name. No, you just kind of treat it as if you're working with the model directly. So anyways, on my main User class, we do have a profile relationship. So we are referencing that here. And if we come back and give this a refresh, now we've loaded the profile. And in these situations, what you'll often want to do is make sure that you eager load it to avoid the n plus one problem.

And in these situations, what you'll often want to do is make sure that you eager load it to avoid the n plus one problem. So we could do something like this. And yeah, we're still going to get the same thing. Now, what we could also do, if we switch back, is maybe we want the location and that's stored on the profile relationship. So something like this. However, if we give this a refresh, well, yes, it's going to work in this case, because this User does have a profile. However, if we fetch a User who does not yet have a profile,

because this User does have a Profile. However, if we fetch a User who does not yet have a Profile, and we give this a run, it's going to blow up, because we're trying to reference location off of null. So this is a good use case for Laravel 5.5's optional helper. We could say optional($this->profile). And so basically, the way it works is this optional function will return kind of a magic class that will dynamically delegate any property calls or method calls to profile, if that happens to be an object.

any property calls or method calls to profile, if that happens to be an object. And if it's a string or something else, it doesn't do anything. So it's just a nice, clean, sort of generic null object implementation. So anyways, if we give that a refresh on the condition that there is no location, we just set that to null. Okay, so anyways, there's actually quite a few things we can do here. We can't cover them all, but definitely take a look at the Laravel documentation to see everything you can do. But anyways, what about the situations where we have a collection of users?

Collections and Pagination6:42

to see everything you can do. But anyways, what about the situations where we have a collection of Users? Okay, well, in those cases, you have two choices. One, there is a collection method we can use. So let's update this to users. And if we now come back and give this a refresh, once again, you'll see that we have an array of Users. But now take a look at this. Imagine we're getting the Users and we're going to paginate them. Now, you may know that in Laravel, if you paginate results and you convert it to JSON,

Imagine we're getting the users and we're going to paginate them. Now, you may know that in Laravel, if you paginate results and you convert it to JSON, Laravel will take care of that for you automatically. So now let's see how that looks here. So when we paginate a collection and then we pass it to a resource, well, now here's the data structure you're going to get. You have your data, your links, which is incredibly useful, and then you also have some meta information. But links is especially useful because you can simply read that to populate your next and previous buttons.

But links is especially useful because you can simply read that to populate your next and previous buttons if you're using JavaScript to build up your pagination. But now you'll see here, if we switch back to User, if we bring back that with method to add basically simple links to the top-level fields, so we said return status is success, and we give that a run, that's no longer going to show up. So in situations where you do need a little more control over the data structure here, what you can do is create a collection-specific resource. So all we have to do for that is include the keyword collection within the resource name,

Custom Collection Resources8:02

what you can do is create a collection-specific resource. So all we have to do for that is include the keyword collection within the resource name, or you can use this collection flag. Either one is fine. In our case, let's use UserCollection. Okay, so now if I switch back to Sublime, you'll now see here's our UserCollection. It looks very similar, but now we're extending ResourceCollection, and it has just a few more bells and whistles specifically for your collections. Let's give this a shot though. We're now going to pull in UserCollection,

Let's give this a shot though. We're now going to pull in User collection, and we can change this to a new User collection. All right, back to Chrome, we'll give this a refresh, and now you'll see we're basically getting the exact same thing as we had before. However, we now have a lot more control over the data structure. So for example, right here, and now we could say, yeah, so we want our structure to be data, and we can use collection to reference the collection of items. So let's come back and give that a refresh, and that doesn't change anything at all.

and we can use collection to reference the collection of items. So let's come back and give that a refresh, and that doesn't change anything at all. But now we can add anything else we need here. So if we refresh, now you'll have foo bar. You could say status is success. Yeah, you can basically modify this however you need to. Anyways, what else? Let's go back to using just a standard UserResource, and then we'll update this like so, UserResource. All right, so let's find that person, give that a refresh.

and then we'll update this like so, UserResource. All right, so let's find that person, give that a refresh. Now you can see we've added additional meta information that we need, but there might be situations where you don't want this to be called data, or you don't want any wrapper at all. So in those situations, what you can do, let me show you. If we go to the Resource class that we're extending, you'll find a method called with, and then also without wrapping. So without wrapping simply disables the wrap entirely, and you can even reference this within your AppServiceProvider like this.

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