GraphQL API с PHP: пошаговый туториал для начинающих

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

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

Начать курс

Введение в GraphQL и PHP

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

В этом руководстве мы создадим простой, но функциональный GraphQL API с использованием библиотеки webonyx/graphql-php. Вы узнаете, как установить зависимости, определить схему, типы, резолверы и обработать запросы. Примеры кода помогут вам быстро начать.

1. Подготовка окружения и установка зависимостей

Для начала убедитесь, что у вас установлен PHP версии 7.4 или выше и Composer — менеджер зависимостей для PHP. Если Composer ещё не установлен, скачайте его с официального сайта.

Создайте новый проект и установите библиотеку webonyx/graphql-php:

mkdir graphql-php-tutorial
cd graphql-php-tutorial
composer init --name="myapp/graphql-demo" --type="project" --no-interaction
composer require webonyx/graphql-php

После установки в папке проекта появится директория vendor и файл composer.json. Также создайте файл index.php — в нём будет весь наш код.

Дополнительно, для удобства работы с HTTP-запросами, установите laminas/laminas-diactoros (популярная PSR-7 реализация) и laminas/laminas-httphandlerrunner:

composer require laminas/laminas-diactoros
composer require laminas/laminas-httphandlerrunner

2. Определение схемы и типов GraphQL

Сердце любого GraphQL API — это схема (schema). Она описывает, какие данные доступны и как их можно запрашивать. В нашем примере мы создадим простую модель "Пользователь" (User) и "Пост" (Post).

Сначала определим типы с помощью класса GraphQL\Type\Definition\ObjectType. Создадим файл schema.php (или добавьте код прямо в index.php).

<?php
require_once __DIR__ . '/vendor/autoload.php';

use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;
use GraphQL\GraphQL;

// Определяем тип User
$userType = new ObjectType([
    'name' => 'User',
    'description' => 'Представляет пользователя системы',
    'fields' => [
        'id' => Type::int(),
        'name' => Type::string(),
        'email' => Type::string(),
    ]
]);

// Определяем тип Post
$postType = new ObjectType([
    'name' => 'Post',
    'description' => 'Пост пользователя',
    'fields' => [
        'id' => Type::int(),
        'title' => Type::string(),
        'content' => Type::string(),
        'author' => $userType, // Связь с пользователем
    ]
]);

Обратите внимание: мы используем Type::int() и Type::string() — это встроенные скалярные типы GraphQL. Поле author ссылается на другой объектный тип, что позволяет строить вложенные запросы.

3. Создание резолверов и фиктивных данных

Резолверы (resolvers) — это функции, которые возвращают данные для каждого поля. В простейшем случае мы можем использовать фиктивные данные (массивы).

Добавим резолверы для корневого типа Query. Именно через него клиенты будут получать данные.

// Фиктивные данные
$users = [
    1 => ['id' => 1, 'name' => 'Иван Петров', 'email' => 'ivan@example.com'],
    2 => ['id' => 2, 'name' => 'Мария Смирнова', 'email' => 'maria@example.com'],
];

$posts = [
    1 => ['id' => 1, 'title' => 'Первая запись', 'content' => 'Текст первой записи', 'author_id' => 1],
    2 => ['id' => 2, 'title' => 'Вторая запись', 'content' => 'Текст второй записи', 'author_id' => 2],
];

// Определяем корневой тип Query
$queryType = new ObjectType([
    'name' => 'Query',
    'fields' => [
        'user' => [
            'type' => $userType,
            'args' => [
                'id' => Type::nonNull(Type::int()),
            ],
            'resolve' => function ($root, $args) use ($users) {
                return $users[$args['id']] ?? null;
            }
        ],
        'users' => [
            'type' => Type::listOf($userType),
            'resolve' => function () use ($users) {
                return array_values($users);
            }
        ],
        'post' => [
            'type' => $postType,
            'args' => [
                'id' => Type::nonNull(Type::int()),
            ],
            'resolve' => function ($root, $args) use ($posts) {
                return $posts[$args['id']] ?? null;
            }
        ],
    ]
]);

Теперь нужно связать поле author в типе Post с данными. Добавим резолвер прямо в определение поля:

$postType = new ObjectType([
    'name' => 'Post',
    'fields' => [
        'id' => Type::int(),
        'title' => Type::string(),
        'content' => Type::string(),
        'author' => [
            'type' => $userType,
            'resolve' => function ($post) use ($users) {
                return $users[$post['author_id']] ?? null;
            }
        ],
    ]
]);

Обратите внимание: резолвер поля author получает родительский объект (пост) в качестве первого аргумента $post.

4. Обработка запроса и запуск API

Теперь соберём всё вместе: создадим схему, обработаем входящий HTTP-

Блоги

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