Before you go, check out these stories!

0
Hackernoon logoFirst impressions on Laravel API Resources by@deleu

First impressions on Laravel API Resources

Author profile picture

@deleuMarco Aurélio Deleu

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-develop
cd responses
touch database/database.sqlite
php artisan make:model Post -mfa
php artisan make:resource UsersWithPostsResource
php artisan make:resource PostsResource
php 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:fresh
php artisan tinker
factory(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

Tags

Become a Hackolyte

Level up your reading game by joining Hacker Noon now!