В одной из предыдущих статей мы разобрались, что такое GraphQL в теории. Сегодня рассмотрим пример создания GraphQL API на Laravel.
Установка библиотеки Graphql
Для создания API воспользуемся пакетом folklore/graphql, который является оберткой пакета webonyx/graphql-php (самой популярной реализации GraphQL для PHP) для использования в Laravel. Установим его через Composer:
composer require folklore/graphql
Если вы используете Laravel 5.5 или выше, то фреймворк настроит пакет автоматически, нужно только опубликовать конфигурационный файл с помощью команды:
php artisan vendor:publish --provider="Folklore\GraphQL\ServiceProvider"
Это создаст новый файл конфигурации config/graphql.php
.
Если вы используете Laravel 5.4 или ниже, то для настройки пакета нужно выполнить следующие шаги:
- Добавить новый сервис провайдер в
config/app.php
:Folklore\GraphQL\ServiceProvider::class,
- Добавить новый фасад в
config/app.php
:GraphQL' => Folklore\GraphQL\Support\Facades\GraphQL::class,
- Опубликовать файл конфигурации для пакета:
php artisan vendor:publish --provider="Folklore\GraphQL\ServiceProvider"
После установки в браузере по адресу /graphiql должен быть доступен графический интерфейс для выполнения запросов GraphQL:
Пример API
Создадим простой API для создания и получения информации о пользователях. Laravel по умолчанию имеет модель User и миграцию для создания соответствующей таблицы в базе данных.
Для начала создадим новый тип User
, запрос UsersQuery
для получения данных о пользователе и мутацию CreateUserMutation
для создания новых пользователей:
php artisan make:graphql:type UserType php artisan make:graphql:query UsersQuery php artisan make:graphql:mutation CreateUserMutation
Ниже приведен код для созданных классов:
GraphQL/Type/UserType.php:
<?php namespace App\GraphQL\Type; use Folklore\GraphQL\Support\Type as BaseType; use GraphQL\Type\Definition\Type; class UserType extends BaseType { protected $attributes = [ 'name' => 'UserType', 'description' => 'A type' ]; public function fields() { return [ 'id' => [ 'type' => Type::nonNull(Type::int()), 'description' => 'The id of the user' ], 'email' => [ 'type' => Type::string(), 'description' => 'The email of user' ], 'name' => [ 'type' => Type::string(), 'description' => 'The name of user' ] ]; } }
GraphQL/Query/UsersQuery.php:
<?php namespace App\GraphQL\Query; use App\User; use Folklore\GraphQL\Support\Query; use GraphQL; use GraphQL\Type\Definition\Type; class UsersQuery extends Query { protected $attributes = [ 'name' => 'UsersQuery', 'description' => 'A query' ]; public function type() { return Type::listOf(GraphQL::type('User')); } public function args() { return [ 'id' => ['name' => 'id', 'type' => Type::int()], 'email' => ['name' => 'email', 'type' => Type::string()] ]; } public function resolve($root, $args) { if (isset($args['id'])) { return User::where('id' , $args['id'])->get(); } else if(isset($args['email'])) { return User::where('email', $args['email'])->get(); } else { return User::all(); } } }
Данный класс используется для получения данных о пользователях. При этом в запрос может передаваться id или email пользователя, для которого мы хотим получить данные.
GraphQL/Mutation/CreateUserMutation.php:
<?php namespace App\GraphQL\Mutation; use App\User; use Folklore\GraphQL\Support\Mutation; use GraphQL; use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; class CreateUserMutation extends Mutation { protected $attributes = [ 'name' => 'createUser', 'description' => 'A mutation' ]; public function type() { return GraphQL::type('User'); } public function args() { return [ 'name' => [ 'type' => Type::nonNull(Type::string()) ], 'email' => [ 'type' => Type::nonNull(Type::string()), 'rules' => ['email', 'unique:users'] ], 'password' => [ 'type' => Type::nonNull(Type::string()), 'rules' => ['min:4'] ] ]; } public function resolve($root, $args, $context, ResolveInfo $info) { $user = new User(); $user->fill($args); $user->save(); return $user; } }
Мутация для создания пользователя принимает на вход имя, email и пароль, и возвращает в ответ информацию о созданном пользователе. Так же для каждого поля могут быть заданы правила валидации, которые используют стандартную валидацию Laravel.
После этого нужно добавить созданные сущности в файл config/graphql.php
:
'schemas' => [ 'default' => [ 'query' => [ 'users' => 'App\GraphQL\Query\UsersQuery' ], 'mutation' => [ 'createUser' => 'App\GraphQL\Mutation\CreateUserMutation' ] ] ], 'types' => [ 'User' => 'App\GraphQL\Type\UserType' ],
Если теперь открыть адрес /graphiql в браузере, вы увидите, что вкладка Docs отображает документацию по только что созданному API. На скриншоте ниже видно, как выглядит результат выполнения запроса на создание нового пользователя и документации по мутации createUser, которая была использована в этом запросе.
Теперь создадим первый запрос на создание пользователя:
mutation { createUser( name: "Test User", email:"test@example.com", password:"qwerty" ) { id, email, name } }
Если все настроено правильно, то сервер вернет следующий ответ:
{ "data": { "createUser": { "id": 1, "email": "test@example.com", "name": "Test User" } } }
Получим данные только что созданного пользователя:
query { users (id: 1) { id email } }
Сервер вернет следующий ответ:
{ "data": { "users": [ { "id": 1, "email": "test@example.com" } ] } }
Как видно, сервер возвращает только те поля пользователя, которые указаны в запросе, что очень удобно и позволяет ускорить выполнение запроса, когда требуется получить только несколько полей для каждой записи. В данном примере мы использовали фильтрацию пользователей по id. Если не передавать в запрос никаких параметров, то API вернет массив всех пользователей.
Заключение
В данной статье мы рассмотрели пример создания GraphQL API на Laravel.
Для запуска API из этой статьи вы можете скачать код с GitHub по ссылке https://github.com/RusinovIG/blog-examples/tree/graphql-example и запустить локально.
Используемый пакет позволяет очень гибко настраивать правила для создания, обновления и получения данных на сервере, при этом, благодаря спецификациям GraphQL, мы получаем самодокументируемый API, что наглядно демонстрируется в примере с помощью встроенной в пакет графической IDE для работы с GraphQL-запросами.
О более сложных примерах использования GraphQL читайте во второй части статьи.
Спасибо за статью! Когда ожидается вторая часть?
На этой неделе выйдет продолжение с более сложными примерами. Подписывайтесь на обновления, чтобы не пропустить)
Добав возможность увеличить картинки, ато каждый раз лупу ищу!!