Создавая свой API, вам может понадобиться промежуточный слой между вашими моделями и JSON-ответами, которые возвращаются пользователям. API Resources в Laravel 5.5 позволяют быстро и легко трансформировать ваши модели и коллекции моделей в желаемое JSON-представление. Перевод автораЭто теория, а на практике мы с вами сегодня используем api-ресурсы для вывода списка пользователей воображаемого веб-проекта. Пример не сложный, но позволяет наглядно понять как работают api-ресурсы. Также, как было заявлено в вводной части, в примере используем два других нововведения из Laravel 5.5: функцию (helper) optional() и возможность создания отдельного файла для фабрики (factory).
В данном примере я использую БД SQLite, но вы можете использовать любую другую.
Для того, чтобы фреймворк «понял», что мы хотим работать с SQLite, нужно изменить настройки соединения с БД в файле .env. Откроем его, и в строке DB_CONNECTION пропишите значение sqlite. Остальные строки данной секции (DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD) нужно удалить. Получится так:
DB_CONNECTION=sqlite
Не забудьте создать файл БД database.sqlite в папке database проекта.
Далее маршруты. Откроем файл web.php (папка routes) и добавим в него следующий маршрут:
Route::resource('api/users', 'Api\UserController')
->only(['index', 'show']);
Как видим, нам нужно, чтобы контроллер реагировал только на действия index и show.
Создадим сам контроллер, я назвал его UserController, потому как в данном проекте мы работаем с пользователями. Для создания контроллера понадобится команда:
php artisan make:controller Api/UserController —resource
Будет создана заготовка контроллера с кучей методов, из которых нам потребуется только два: index() и show($id). Остальные можно удалить.
Измените код контроллера на следующий:
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Resources\UserResource;
use App\User;
class UserController extends Controller
{
public function index()
{
$users = User::with('profile')->get();
return UserResource::collection($users);
}
public function show(User $user)
{
return new UserResource($user);
}
}
В методе index() мы используем статический метод collection() класса UserResource для вывода коллекции (списка) моделей пользователей в формате JSON.
В методе show() мы создаем новый объект класса UserResource из модели пользователя User и трансформируем его в JSON-представление.
Из кода контроллера следует, что далее нам следует поработать с моделью пользователя User, а затем создать класс UserResource, который требуется в контроллере.
Модель User существует по-умолчанию, поэтому нам не придется ее создавать, но для примера мы туда кое-что добавим. Чтобы немного усложнить проект создадим дополнительную модель Profile (профиль). В данной модели у нас будет поле location, которое будет содержать местоположение пользователя. Это поле будем выводить вместе с остальными полями из модели User (id, name, email). Как это будет реально выглядеть смотрите на рисунке в конце материала. Модель User и модель Profile должны быть соединены отношением hasOne. Для этого в файл модели User, внутри тела класса, после массивов $fillable и $hidden добавим код:
public function profile() {
return $this->hasOne(Profile::class);
}
Теперь нужно создать саму модель Profile. Для этого используем команду:
php artisan make:model Profile -m
Этой командой мы также создали файл миграции create_profiles_table.php (опция -m в команде make:model). Откроем его (папка database/migrations). В метод up() добавим следующее содержимое:
Schema::create('profiles', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->string('location');
$table->timestamps();
});
В модели Profile, в нашем примере, ничего менять или добавлять не требуется.
Запустим миграцию, чтобы создать таблицы в БД:
php artisan migrate
Наполним таблицу профилей случайными данными, используя Faker. Для этого запустим команду:
php artisan make:factory ProfileFactory
После этого в папке database/factories у нас будут 2 файла: UserFactory.php (был изначально) и ProfileFactory.php. Как видите, в Laravel 5.5 каждая фабрика теперь имеет отдельный файл. В файле UserFactory.php ничего менять не будем. Откроем для изменения файл ProfileFactory.php. Внутри метода define() в возвращаемый массив добавим элемент:
'location' => $faker->unique()->address
Создадим файл UsersTableSeeder.php, в котором укажем сколько связных записей нам нужно создать в таблицах users и profiles. Для этого запустим команду:
php artisan make:seeder UsersTableSeeder
Откроем созданный файл (UsersTableSeeder.php). В файле метод run() изменим следующим образом:
public function run()
{
factory(App\User::class, 10)->create()->each(function($u) {
$u->profile()->save(factory(App\Profile::class)->make());
});
}
Здесь мы указываем, что нужно создать 10 связных записей в таблицах users и profiles.
Чтобы данный файл запустился его нужно добавить в очередь запуска через файл DatabaseSeeder.php. Откроем его и в методе run() расскоментируем строчку:
$this->call(UsersTableSeeder::class);
Ну а теперь самое приятное, запустим все это на исполнение командой:
php artisan db:seed
С моделью пользователя User и ее связной моделью Profile мы разобрались, теперь пришел черед создать класс UserResource (наконец-то!), который мы используем в контроллере. Данный класс создадим следующей командой:
php artisan make:resource UserResource
Откроем файл класса (папка app/Http/Resources). Заменим содержимое метода toArray() на следующее:
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'location' => optional($this->profile)->location
];
Заметьте, что здесь мы используем функцию (helper) optional(), которая также появилась в Laravel 5.5. Мы бы могли ее здесь и не использовать, а написать так:
'location' => $this->profile->location
Но тогда, если бы у нас не было создано связной записи в таблице profiles, для данного пользователя, то мы бы получили ошибку, а с функцией optional() поле location будет просто заполнено значением null. Попробуйте создать отдельную запись пользователя (без профиля) и удалите функцию optional() из кода.
Отдельную запись пользователя можно создать, запустив команду:
php artisan tinker
А затем команду:
factory(App\User::class, 1)->create();
На этом все. Результат работы приложения по адресу: /api/users (действие index) будет следующим:


Оставьте свой комментарий
Комментарии