Введение в GraphQL с PHP: почему это стоит попробовать
GraphQL — это современный язык запросов для API, разработанный Facebook. В отличие от REST, где каждый эндпоинт возвращает фиксированную структуру данных, GraphQL позволяет клиенту запрашивать только те поля, которые ему нужны. Это сокращает объем передаваемых данных и упрощает разработку сложных приложений.
В этом туториале мы создадим полноценный GraphQL API на PHP с использованием библиотеки webonyx/graphql-php. Вы узнаете, как определить схему, написать резолверы, обработать запросы и мутации, а также протестировать API через GraphiQL.
Предполагается, что у вас установлен PHP 8.0+ и Composer. Если нет — начните с их установки.
Установка и настройка проекта
Шаг 1: Создание проекта и установка зависимостей
Создайте новую директорию для проекта и инициализируйте Composer:
mkdir graphql-php-tutorial
cd graphql-php-tutorial
composer init
Установите библиотеку webonyx/graphql-php:
composer require webonyx/graphql-php
Также установите nikic/fast-route для простой маршрутизации (опционально, но удобно):
composer require nikic/fast-route
Шаг 2: Структура проекта
Создайте следующую структуру папок:
graphql-php-tutorial/
├── src/
│ ├── Schema/
│ │ └── schema.php
│ ├── Resolvers/
│ │ ├── QueryResolver.php
│ │ └── MutationResolver.php
│ └── Data/
│ └── Database.php
├── public/
│ └── index.php
├── vendor/
└── composer.json
Создание схемы GraphQL
Шаг 3: Определение типов и схемы
Создадим простую модель данных: пользователь (User) и пост (Post). Откройте src/Schema/schema.php и добавьте следующий код:
<?php
namespace App\Schema;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema as GraphQLSchema;
class Schema
{
public static function build(): GraphQLSchema
{
// Тип User
$userType = new ObjectType([
'name' => 'User',
'fields' => [
'id' => Type::int(),
'name' => Type::string(),
'email' => Type::string(),
'posts' => [
'type' => Type::listOf(function() use (&$postType) {
return $postType;
}),
'resolve' => function($user) {
return \App\Resolvers\QueryResolver::getPostsByUser($user['id']);
}
]
]
]);
// Тип Post
$postType = new ObjectType([
'name' => 'Post',
'fields' => [
'id' => Type::int(),
'title' => Type::string(),
'content' => Type::string(),
'author' => [
'type' => $userType,
'resolve' => function($post) {
return \App\Resolvers\QueryResolver::getUserById($post['author_id']);
}
]
]
]);
// Корневой тип Query
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'users' => [
'type' => Type::listOf($userType),
'resolve' => function() {
return \App\Resolvers\QueryResolver::getAllUsers();
}
],
'user' => [
'type' => $userType,
'args' => [
'id' => Type::nonNull(Type::int())
],
'resolve' => function($root, $args) {
return \App\Resolvers\QueryResolver::getUserById($args['id']);
}
],
'posts' => [
'type' => Type::listOf($postType),
'resolve' => function() {
return \App\Resolvers\QueryResolver::getAllPosts();
}
]
]
]);
// Корневой тип Mutation
$mutationType = new ObjectType([
'name' => 'Mutation',
'fields' => [
'createUser' => [
'type' => $userType,
'args' => [
'name' => Type::nonNull(Type::string()),
'email' => Type::nonNull(Type::string())
],
'resolve' => function($root, $args) {
return \App\Resolvers\MutationResolver::createUser($args);
}
],
'createPost' => [
'type' => $postType,
'args' => [
'title' => Type::nonNull(Type::string()),
'content' => Type::nonNull(Type::string()),
'author_id' => Type::nonNull(Type::int())
],
'resolve' => function($root, $args) {
return \App\Resolvers\MutationResolver::createPost($args);
}
]
]
]);
return new GraphQLSchema([
'query' => $queryType,
'mutation' => $mutationType
]);
}
}
Реализация резолверов и базы данных
Шаг 4: Создание резолверов для запросов
Файл src/Resolvers/QueryResolver.php:
<?php
namespace App\Resolvers;
use App\Data\Database;
class QueryResolver
{
public static function getAllUsers(): array
{
return Database::getUsers();
}
public static function getUserById(int $id): ?array
{
$users = Database::getUsers();
foreach ($users as $user) {
if ($user['id'] === $id) {
return $user;
}
}
return null;
}
public static function getAllPosts(): array
{
return Database::getPosts();
}
public static function getPostsByUser(int $userId): array
{
$posts = Database::getPosts();
return array_filter($posts, function($post) use ($userId) {
return $post['author_id'] === $userId;
});
}
}
Шаг 5: Создание резолверов для мутаций
Файл src/Resolvers/MutationResolver.php:
<?php
namespace App\