First impressions on Laravel API Resources

Written by deleugpn | Published 2017/08/24
Tech Story Tags: laravel | api | software-development

TLDRvia the TL;DR App

Last night Taylor Otwell finally introduced what can be the beginning of replacing Fractal when developing APIs on Laravel 5.5. This is my first trial-and-run at it.

The interesting stuff starts at step 4.

1- Install clean Laravel 5.5 project

composer create-project laravel/laravel responses dev-developcd responsestouch database/database.sqlitephp artisan make:model Post -mfaphp artisan make:resource UsersWithPostsResourcephp artisan make:resource PostsResourcephp artisan make:controller UsersController --resource

Change your .env file to use SQLite and remove every other database variable.

DB_CONNECTION=sqlite

2- Prepping the database

  • The posts migration database/migrations/______create_posts_table.php

Schema::create('posts', function (Blueprint $table) {$table->increments('id');$table->string('title');$table->string('body');$table->unsignedInteger('user_id');$table->timestamps();});

  • The Post Factory database/factories/PostFactory.php

**<?php

use** Faker\Generator as Faker;

$factory->define(App\Post::class, function (Faker $faker) {return ['title' => $faker->sentence,'body' => $faker->paragraph,'user_id' => function () {return factory(\App\User::class);}];});

  • The User has Posts relationship app/User.php

public function posts(){return $this->hasMany(Post::class);}

  • Avoid Mass Assignment on Posts app/Post.php

**<?php

namespace** App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model{protected $guarded = [];}

  • Seeding the database

php artisan migrate:freshphp artisan tinkerfactory(App\Post::class)->times(2)->create();factory(App\Post::class)->times(2)->create(['user_id' => 1]);

3- Setup the Route

Route::apiResource('/users', 'UsersController');

4- Transforming Model into a Resource

/*** Display a listing of the resource.** @param User $user* @return _\Illuminate\Http\Response*/_public function index(User $user){return new UsersWithPostsResource($user->paginate());}

5- Users With Posts Resource

**<?php

namespace** App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;

class UsersWithPostsResource extends Resource{/*** Transform the resource into an array.** @param \Illuminate\Http\Request* @return array*/ public function toArray($request){// Eager load$this->resource->load('posts');

    **return** $this->resource->map(**function** ($item) {  
        **return** \[  
            'name' => $item->name,  
            'email' => $item->email,  
            'posts' => **new** PostsResource($item->posts)  
        \];  
    });  
}  

}

6- Posts Resource

**<?php

namespace** App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;

class PostsResource extends Resource{/*** Transform the resource into an array.** @param \Illuminate\Http\Request* @return array*/ public function toArray($request){return $this->resource->map(function ($item) {return ['title' => $item->title];});}}

7- Conclusion

The first clear difference when comparing to Fractal is that the resource have easy and direct access to the whole collection instead of a per-object basis. This means that when transforming a collection of Users, you can easily eager load every post without N+1 queries.

It is also easy to nest transformation since you can just spawn a new Resource class that will transform your data as needed.

I expect to write a more detailed post about it once I start digging more into the possibilities.

Followup

This was the first article on API Resources coming to Laravel 5.5. You can find the 2nd article on this subject here: https://medium.com/@deleugpn/reusable-api-resource-with-nested-relationship-laravel-5-5-c654c7243869


Published by HackerNoon on 2017/08/24