Введение: 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 последовательных запроса