Прошлой ночью Taylor Otwell наконец представил что может стать началом замены Fractal при разработке API на фреймворке Laravel 5.5. Это моя пробная версия статьи, поехали.
Интересный материал начинается с 4-го шага.
1. Установка приложения
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
Пропишите в файле .env
проекта использование базы SQLite, убрав все прочие.
DB_CONNECTION=sqlite
2. Подготовка базы данных
2.1. Создадим миграцию The posts migration
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->string('body');
$table->unsignedInteger('user_id');
$table->timestamps();
});
2.2. Создадим factory: database/factories/PostFactory.php
<?php
use FakerGenerator as Faker;
$factory->define(AppPost::class, function (Faker $faker) {
return [
'title' => $faker->sentence,
'body' => $faker->paragraph,
'user_id' => function () {
return factory(AppUser::class);
}
];
});
2.3 Добавим отношение в модель app/User.php
public function posts()
{
return $this->hasMany(Post::class);
}
2.4 Избегайте массового присвоения в сообщениях app/Post.php
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Post extends Model
{
protected $guarded = [];
}
2.5 Заполнение базы тестовыми данными
php artisan migrate:fresh
php artisan tinker
factory(AppPost::class)->times(2)->create();
factory(AppPost::class)->times(2)->create(['user_id' => 1]);
3. Настройка роутов
Route::apiResource('/users', 'UsersController');
4. Преобразование модели в ресурсы
/**
* Display a listing of the resource.
*
* @param User $user
* @return IlluminateHttpResponse
*/
public function index(User $user)
{
return new UsersWithPostsResource($user->paginate());
}
5. Юзеры с ресурсными постами
<?php
namespace AppHttpResources;
use IlluminateHttpResourcesJsonResource;
class UsersWithPostsResource extends Resource
{
/**
* Transform the resource into an array.
*
* @param IlluminateHttpRequest
* @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. Ресурсы постов
<?php
namespace AppHttpResources;
use IlluminateHttpResourcesJsonResource;
class PostsResource extends Resource
{
/**
* Transform the resource into an array.
*
* @param IlluminateHttpRequest
* @return array
*/
public function toArray($request)
{
return $this->resource->map(function ($item) {
return [
'title' => $item->title
];
});
}
}
7. Вывод
Первая явная разница в сравнении с Fractal в том, что ресурс имеет простой и прямой доступ ко всей коллекции, а не к каждому объекту. Это означает, что при преобразовании коллекции пользователей Вы можете легко загружать каждую запись без N+1 запросов.
Вы можете легко трансформировать «точки», так как можете просто создать новый класс ресурсов для преобразования Ваших данных по мере необходимости.
Я хочу более подробно раскрыть эту тему, как только нарою больше возможностей Laravel API Resources.
От переводчика
Посчитал эту тему интересной и решил перевести с адаптацией языка. Прошу ногами не пинать. Также приветствуются линки на оригинальную и переведенную доку по данной тематике.
Автор: Андрей Николаевич