Using Laravel 5.5 Resources to create your own {JSON:API} formatted API

Ever since I started writing APIs in Laravel I have been using the awesome Fractal package from The League of Extraordinary Packages and it has served its purpose exceptionally well for transforming raw models into JSON:API and other serialising methods, and until now it was really the only option.

Introducing Laravel 5.5 Resource Classes

We now have Resource classes we can use for our APIs out of the box in Laravel 5.5 without having to install any 3rd party packages.

What are Resource Classes and why should I use it?

A Resource class is a way to transform data from one format to another. Simply put, if we have a Article model and we want to manipulate the data or remove certain fields from the model before sending that in our response, it is difficult to do so by just responding with;

Granted this will give you a valid response, maybe something like this;

But what if you wanted to format your responses to a standard like JSON:API or any one of the other numerous standards out there. We would need to override the Model’s toArray implementation and now we are breaking the single responsibility rule. Why should the model care how to format a response to the end user? It shouldn’t! and this is where we can now utilise Resource classes in Laravel 5.5. Instead of doing what we did above we can now create a Laravel Resource using artisan and transform our model in any way we like.

For the rest of this article I’m going to show you how to utilise Laravel’s new Resource classes to implement the example on the JSON:API specification home page, which looks something like this;

jsonapi.org example json:api

Create our Laravel Application

First things first we need a test app to work with;

laravel new articles-api

Bear with me as I’ll try to fly through the boring setup parts as fast as possible. I’m also going to assume you know how to connect to a database and setup your environment, etc so that I won’t have to go through that in this article.

Continuing…

Generate our database and models

First things first we need some data so lets make some migrations.

php artisan make:model Article -crmf
php artisan make:model People -mf
php artisan make:model Comment -mf

As this is a tutorial we don’t want to waste time on the boring stuff so this command creates the model, resource controller (cr), migration (m) and factory (f) all in one go. Woohoo!

Lets fill these up with some boiler plate so we can get to the good stuff.

Open your migration files and add;

Now that you have the migrations lets migrate;

php artisan migrate

You also have factory classes available to seed some test data but I’ll leave that up to you to fill in the blanks for those.

Building our JSON:API using Resource Classes

Now that we have our database and presumably you have seeded your tables with some fake data we can move on to the fun stuff and what you really came here for.

A bit of Theory First

When dealing with resources and how to transform them into responses for the client we basically have 2 types, an item and a collection. An item resource as you might have guessed is basically a one to one representation of our model where as a collection is the representation of many items. Collections may also have meta data and other navigation information as well.

In terms of JSON:API we can represent an item like this;

Whereas a collection would be represented like this (in it’s basic form);

Articles Collection

Now that we know the difference between an item and a collection lets try to replicate these using Resource classes.

First we need to generate 2 classes one to handle the item and the other to handle the collection. Luckily we can utilise artisan to do this.

php artisan make:resource ArticleResource
php artisan make:resource ArticlesResource --collection

You will now have a new directory under app/Http/Resources where all these resources will reside.

In each one of these classes you will have a toArray method which is where we will transform our models the way we want them. So lets change the App\Http\Resource\ArticleResource so it transforms our Article model into a JSON:API resource;

As you can see we have top level type, id and attributes keys to start with. We’ll expand on this to include links and relationships as well in a bit but first lets create our controller and routes so we can see this in action.

php artisan make:controller --resource ArticleController

This will give us a resource based controller to start putting our RESTful API together. Now we need to tell our controller actions to use our newly created resource in the show method so lets add that.

And the route;

For simplicity we can just use a resource based route entry hear, we’ll be adding to it a bit so it not totally wasted.

So now you should have a fully operational API which can show an article resource by going to the /api/articles/{id} you should get a response back like this;

Obviously you’ll need to add some data to your database and serve the API — HINT: php artisan serve then go to http://127.0.0.1/api/articles/1 in Postman watch the magic.

Making this JSON:API compliant

All this is great and out of the box works a treat, but this article is about making use of the Resource classes to generate JSON:API compliant. To this the item shouldn’t have the data top level key. Well Laravel makes this easy we just need to tell the resource we don’t want it wrapped, so before calling the resource we need to call the static method withoutWrapping(), easy;

Now you’ll get this when you call that endpoint;

Awesome that was easy. Ok, so now lets add some more of the JSON:API goodness like links and relationships. Open up ArticleResource and lets add them.

So pretty easy right we’ve added our article relationships and links. The self link will work out of the box because we added a route resource before to the controller so it knows how to resolve this route but we also have a new resource for our relationships which will need to be created. Easy, artisan to the rescue;

php artisan make:resource ArticleRelationshipResource

And just for expedience we’ll also create the rest of our resources now so we don’t have to later.

php artisan make:resource AuthorIdentifierResource
php artisan make:resource CommentIdentifierResource
php artisan make:resource --collection ArticleCommentsRelationshipResource
php artisan make:resource --collection ArticlesResource

We’ll pass $this to our ArticleRelationshipResource so we have access to the Article model and it’s relationships.

Notice in this class we have a new method with which is used to add meta data to our resources. This is handy to split out all non entity based data out from your resource.

So we’ve handled links and relationships now and we are pretty much done generating an item resource. I’ll let you work out the other resources and the data that needs to go in them (hint: it’s on github — link at the end of the article).

Collection Resources

Last thing to do is the collection resource, well this couldn’t be any easier. Lets open up our ArticleController and do this.

So just like the show method we just return the resource and pass the collection of articles to it in it’s constructor. In this case we want to get a paginated list of Articles and eager load the relationships we want. Our ArticlesResource looks like this.

How easy is that, we are just using the ArticleResource which we have already done all the heavy lifting with and utilising the static collection method passing the paginated articles collection from the controller to be transformed.

Included entities

This is pretty good but we are still missing one part of our JSON:API resource and that is the unique list of included entities. So let’s add those now;

Now you can see the reason we eager loaded the relationships in the controller. For JSON:API to be truely slim in it’s output we need a unique list of all related resources which can be referenced by the resource identifiers, aka "data": {"type": "people", "id": "9"}.

It turns out this is fairly straight forward to do with the Collection flatMap and map callback methods. flatMap is needed for collection relationships and map is need to item relationships. These will return collections of our relationships for all entities in our collection, so in this case we have multiple articles with authors and comments. We get new collections of all authors and comments for all articles and then merge them and make them unique.

Once we have a unique list of all relationships we need to get the corresponding resource class and instantiate that with our include. We just return this new collection of resources back and assign it to the included key and we are done. You should expect your api to output something along the lines of;

So now you can see the list of unique included resources which relate to all our articles.

Conclusion

I’ve tried to show how to use Laravel 5.5 Resources to create JSON:API compliant responses and it is surprisingly easy once you understand the basics of how they work.

I’ve also not included all the code in this article to actually make this application work if you are following along with the code as it would hae made the article very repetitive and boring (hopefully it isn’t boring already). If you want to explore these resources more you can checkout the the repo at github.com which is a fully working app and please if you see any issues or find a better way to handle the included data submit a PR and I’ll consider it or at least discuss it with you.

I hope you found this informative and start making use of Laravel’s new resources in 5.5.