Creating APIs in Laravel 5.5 using API resources

Published Sep 02, 2017
Creating APIs in Laravel 5.5 using API resources

For about 2 years I have been using Fractal for my API development.

If there was one thing that I always wanted in Laravel, it was exactly that. Transforming your data in order to build better APIs.

Don’t get me wrong, Fractal is great, however I always prefer to stay around the framework. If there is really no need to use a library, then I don’t! I don’t like to complicate things with 3rd party libraries.

Now, it’s been almost over a year that I have been working with front-end frameworks like Vue and React and I love it. Thus, the only thing that I do with Laravel now, is to create APIs. Fractal was the number one library to download whenever I had to create an API. That’s not the case anymore.

In Laravel 5.5, we now have API resources and let me tell you, I AM VERY EXCITED.

Laravel’s API resources are literally based on Fractal, thus it did not take much to understand how to use them. So let’s get started…

Creating the Laravel app

Create the Laravel app with the usual command

composer create-project laravel/laravel Laravel55Api

Once you do that, rename your .env.example file to .env and generate your Laravel key with the command

php artisan key:generate

Run the server

php artisan serve

Creating a product resource

Api resources in Laravel is the new feature that will transform your models and model collections into JSON. So let’s create a resource for product.

php artisan make:resource Product

You can find your Product resource, inside app/Http/Resources

Of course we need a migration, a model, and a controller for product. We can quickly do all that with this command.

php artisan make:model Product -mc

Open the product migration and change the up function to this one:

public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->integer('price');
        $table->timestamps();
    });
}

Notice that price is an integer. Never store your price data as double or float, because 3rd party services such as Stripe and PayPal, will read them differently. By storing the price as an integer, you work with cents and all you have to do is to format the amount.

Now connect your Laravel application with a database and migrate the tables.

This is not a Laravel 101 post, so I am not going through that.

Now what?

So, up to now, we have the model, the controller, the migration, and the resource that as we said will transform your models and model collections into JSON. Now what?

First of all, what is a resource class? What is the Product class we created inside the resources folder? A resource class represents a single model that needs to be transformed into a JSON structure.

With that being said, let’s open the Product.php resource class.

We have a toArray method, that method is used to return the array of attributes that should be converted to JSON when sending the response.

Let’s change it so we can have a better idea.

public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'price' => $this->price,
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

Now, that means that we are going to get back as a response id, name, price, created_at, and updated_at.

If we do not include the price inside the toArray method, then we do not return it in our JSON. Cool ahhh?

Using the Product resource

Let’s move on and use both our controller and the product resource that we just updated its toArray method.

This is how the product controller must look like:

<?php

namespace App\Http\Controllers;

use App\Product;
use App\Http\Resources\Product as ProductResource;

class ProductController extends Controller
{
    public function show ($id)
    {
        return new ProductResource(Product::find($id));
    }
}

We simply pass a product to the product resource class in order to transform it.
Let’s create the route for the show method and take a look at the result.

Open the api.php file and OUTSIDE of the route middleware, create this route.

Route::get('/products/{id}', 'ProductController@show');

Now, create manually a new product inside your products table so you have a sample product to play with and then visit http://127.0.0.1:8000/api/products/1.
You should get this result:

1*RTCsxVS_FsjYGjMqjZxWFw.png

Now let’s play a bit with our resource. Suppose you DO NOT want to make public the price of a product, all you have to do is to simply remove it from your toArray method. Once, you remove the price from the toArray method, then you should get this result, which of course does not include the price:

1*_JUcYPI01E9kvSL1hkga6Q.png

Is that all?

Of course not! Since the toArray method is simply a method, it means that you can include additional information.

Suppose we want to include a “test” info, then simply change your toArray method.

public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'test' => 'This is just a test',
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

And this is the result:
1*73oiUxJd4bLUiDYuigACyg.png

However, something very important is that you should always return the correct data type. Take a look at the price in the first screenshot, it returns as an integer, but we can still force it to be an integer, by saying (int) $this->price.
Now, take a look at the create_at and updated_at timestamps. What if all you wanna do is to return a string of the actual timestamp? Then you can typecast them to a string like in this case:

public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'test' => 'This is just a test',
        'created_at' => (string)$this->created_at,
        'updated_at' => (string)$this->updated_at,
    ];
}

Now the result is this one:

1*5YLHEPylivREKNTdDXkz6w.png

Let’s call it a post

This is only a small sample of what you can do with Laravel’s API resources.
But if I continue like this, this post will take you forever to read.
So, let’s call it a post, but just so you know, we still have pagination, resource collections, how to include relationships, data wrapping, and more to discuss about!

Discover and read more posts from Renato Hysa
get started
Enjoy this post?

Leave a like and comment for Renato