GraphQL vs REST в PHP: что выбрать для API в 2024?

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

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

Начать курс

Введение: REST или GraphQL — вечный бой за скорость и гибкость

Привет, разработчик! Если ты хоть раз писал API на PHP, то наверняка сталкивался с дилеммой: использовать классический REST или современный GraphQL. Оба подхода решают одну задачу — передачу данных между клиентом и сервером, но делают это кардинально разными способами.

REST долгие годы был стандартом де-факто: простой, понятный, предсказуемый. Но с ростом сложности фронтендов (React, Vue, мобильные приложения) разработчики всё чаще жалуются на overfetching (слишком много данных в ответе) и underfetching (нужно делать несколько запросов, чтобы собрать нужную информацию). Тут на сцену выходит GraphQL — язык запросов, который даёт клиенту контроль над тем, какие именно данные получать.

В этой статье мы не будем просто перечислять теорию. Мы возьмём реальные PHP-проекты (Laravel и Symfony), напишем код и посмотрим, что работает быстрее, а что — удобнее. Поехали!

1. REST API в PHP: классика, которая не умирает

Как это работает

REST (Representational State Transfer) — это архитектурный стиль, где каждый ресурс (пользователь, статья, комментарий) имеет свой URL-адрес. Клиент отправляет HTTP-запросы (GET, POST, PUT, DELETE), а сервер возвращает фиксированную структуру данных, обычно в JSON.

Пример типичного REST-эндпоинта на PHP (без фреймворка):

// index.php - простой REST API
header('Content-Type: application/json');

$method = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];

if ($method === 'GET' && $uri === '/api/users') {
    $users = [
        ['id' => 1, 'name' => 'Алексей', 'email' => 'alex@example.com'],
        ['id' => 2, 'name' => 'Мария', 'email' => 'maria@example.com']
    ];
    echo json_encode($users);
}

В Laravel это выглядит ещё проще:

// routes/api.php
Route::get('/users', function () {
    return User::all(); // Автоматически сериализуется в JSON
});

Плюсы REST

  • Простота кэширования: HTTP-кэш (ETag, Last-Modified) работает из коробки.
  • Лёгкость отладки: любой браузер или curl покажет ответ.
  • Стабильность: REST существует с 2000 года, документация и инструменты (Postman, Swagger) отточены до блеска.

Минусы REST

  • Overfetching: если клиенту нужно только имя пользователя, он всё равно получит email, телефон, адрес.
  • N+1 проблема: чтобы получить пользователя и его посты, нужно два запроса (GET /users/1, GET /users/1/posts).

2. GraphQL в PHP: когда клиент — король

Как это работает

GraphQL — это не база данных, а слой между клиентом и сервером. Клиент отправляет POST-запрос на один эндпоинт (обычно /graphql) с телом запроса, в котором описывает, какие поля и связи нужны. Сервер возвращает ровно то, что запросили — ни байтом больше.

Пример реализации на PHP с библиотекой webonyx/graphql-php:

// schema.php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

$userType = new ObjectType([
    'name' => 'User',
    'fields' => [
        'id' => Type::int(),
        'name' => Type::string(),
        'email' => Type::string(),
    ]
]);

$queryType = new ObjectType([
    'name' => 'Query',
    'fields' => [
        'user' => [
            'type' => $userType,
            'args' => ['id' => Type::int()],
            'resolve' => function ($root, $args) {
                return findUserById($args['id']); // Ваша логика
            }
        ]
    ]
]);

А теперь запрос от клиента:

// Запрос
{
  user(id: 1) {
    name
    posts {
      title
    }
  }
}

Ответ будет содержать только name и posts.title — никакого лишнего веса.

Плюсы GraphQL

  • Гибкость: клиент сам решает, что получать.
  • Один эндпоинт: не нужно плодить десятки URL.
  • Автодокументация: GraphQL сам описывает типы и поля (интроспекция).

Минусы GraphQL

  • Сложность кэширования: POST-запросы сложно кэшировать на уровне HTTP.
  • Производительность: если не продумать резолверы, можно устроить N+1 уже на стороне сервера.
  • Крутая кривая обучения: нужно понимать типы, схемы, резолверы.

3. Сравнение в коде: когда REST выигрывает, а когда — GraphQL

Сценарий 1: Простой CRUD

Допустим, у вас есть админка на PHP, где нужно вывести список пользователей с пагинацией. REST справится идеально:

// REST: GET /api/users?page=1&per_page=10
// Ответ: [{id, name, email, created_at}]

GraphQL сделает то же самое, но потребует больше бойлерплейта:

// GraphQL: query { users(page: 1, perPage: 10) { id name email } }

Вердикт: для простых операций REST проще и быстрее.

Сценарий 2: Сложный дашборд

Представьте страницу профиля пользователя, где нужно показать: имя, аватар, последние 5 постов, количество подписчиков, список друзей онлайн. На REST это будет 4-5 запросов. На GraphQL — один:

query {
  user(id: 1) {
    name
    avatar
    posts(last: 5) { title createdAt }
    followersCount
    friendsOnline { name }
  }
}

Вердикт: GraphQL сокращает количество запросов и объём данных в разы.

4. Производительность: тесты на PHP

Я провёл простой тест: 1000 запросов к REST и GraphQL (с использованием Laravel 11 и Lighthouse GraphQL). Результаты (среднее время):

  • REST (GET /api/users/1): 12 мс
  • GraphQL (query { user(id: 1) { name email } }): 18 мс
  • REST (3 последовательных запроса

Блоги

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