GraphQL в PHP: библиотека webonyx/graphql-php для создания API

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

GraphQL библиотека PHP: webonyx/graphql-php

В современной веб-разработке всё чаще возникает потребность в гибких и эффективных API. Традиционные REST-сервисы часто страдают от избыточной или недостаточной загрузки данных. GraphQL — это язык запросов и среда выполнения, созданная Facebook, которая позволяет клиентам запрашивать именно те данные, которые им нужны. Для PHP одной из самых популярных реализаций является библиотека webonyx/graphql-php.

Эта библиотека предоставляет полный набор инструментов для построения GraphQL-серверов на PHP: от определения схемы типов до обработки сложных запросов с вложенными связями. Она идеально подходит для создания современных API для веб-приложений, мобильных приложений и SPA (Single Page Applications).

Основные возможности webonyx/graphql-php

  • Полная поддержка спецификации GraphQL (июнь 2018) — все типы, директивы, переменные и фрагменты.
  • Система типов на основе PHP-объектов — определение типов, интерфейсов, union-типов и enum.
  • Встроенные резолверы — возможность задавать логику получения данных для каждого поля.
  • Валидация запросов — автоматическая проверка синтаксиса и типов.
  • Поддержка ленивой загрузки — данные подгружаются только по запросу.
  • Совместимость с популярными фреймворками — Laravel, Symfony, Yii2 через пакеты-обёртки.

Установка и настройка

Установка осуществляется через Composer:

composer require webonyx/graphql-php

Для работы потребуется PHP 7.1+ с расширением mbstring. После установки создадим простой сервер.

Пример: создание GraphQL-схемы

Рассмотрим базовый пример — получение списка книг и авторов. Сначала определим типы:

<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;

// Тип "Author"
$authorType = new ObjectType([
    'name' => 'Author',
    'fields' => [
        'id' => Type::int(),
        'name' => Type::string(),
        'books' => [
            'type' => Type::listOf($bookType), // будет определён ниже
            'resolve' => function ($author) {
                // Предположим, есть функция getBooksByAuthorId()
                return getBooksByAuthorId($author['id']);
            }
        ]
    ]
]);

// Тип "Book" (определяем с замыканием для циклических ссылок)
$bookType = new ObjectType([
    'name' => 'Book',
    'fields' => function() use ($authorType) {
        return [
            'id' => Type::int(),
            'title' => Type::string(),
            'author' => [
                'type' => $authorType,
                'resolve' => function ($book) {
                    return getAuthorById($book['author_id']);
                }
            ]
        ];
    }
]);

// Тип "Query"
$queryType = new ObjectType([
    'name' => 'Query',
    'fields' => [
        'books' => [
            'type' => Type::listOf($bookType),
            'resolve' => function() {
                return getAllBooks();
            }
        ],
        'author' => [
            'type' => $authorType,
            'args' => [
                'id' => Type::nonNull(Type::int())
            ],
            'resolve' => function($root, $args) {
                return getAuthorById($args['id']);
            }
        ]
    ]
]);

// Создаём схему
$schema = new Schema([
    'query' => $queryType
]);

Обработка запроса

Теперь напишем код, который принимает GraphQL-запрос и возвращает результат:

<?php
use GraphQL\GraphQL;
use GraphQL\Error\DebugFlag;

// Получаем тело запроса из входящего POST-запроса
$rawInput = file_get_contents('php://input');
$input = json_decode($rawInput, true);
$query = $input['query'];
$variableValues = isset($input['variables']) ? $input['variables'] : null;

try {
    $result = GraphQL::executeQuery($schema, $query, null, null, $variableValues);
    $output = $result->toArray(DebugFlag::INCLUDE_DEBUG_MESSAGE);
} catch (\Exception $e) {
    $output = [
        'errors' => [
            ['message' => $e->getMessage()]
        ]
    ];
}

header('Content-Type: application/json');
echo json_encode($output);

Пример клиентского запроса

Рекомендаций