Введение в GraphQL и PHP
GraphQL — это язык запросов для API и среда выполнения для выполнения этих запросов с существующими данными. В отличие от REST, где вы получаете фиксированную структуру ответа, GraphQL позволяет клиенту запрашивать только те данные, которые ему действительно нужны. Это делает API более гибким и эффективным.
В этом туториале мы создадим простой GraphQL API на PHP с нуля. Вы узнаете, как установить необходимые библиотеки, определить схему, написать резолверы и обработать запросы. Статья рассчитана на начинающих разработчиков, знакомых с основами PHP и базами данных (например, MySQL или SQLite).
Мы будем использовать библиотеку webonyx/graphql-php — это самый популярный и стабильный пакет для реализации GraphQL на PHP. В конце вы сможете запустить свой собственный GraphQL-сервер и выполнять к нему запросы через любой HTTP-клиент (например, cURL или Insomnia).
Установка и настройка проекта
Шаг 1: Создание проекта и установка зависимостей
Для начала создадим новую директорию для проекта и инициализируем Composer:
mkdir graphql-php-tutorial
cd graphql-php-tutorial
composer init
Затем установим библиотеку webonyx/graphql-php:
composer require webonyx/graphql-php
Также нам понадобится PSR-7 совместимый HTTP-сервер. Для простоты используем встроенный PHP-сервер и библиотеку guzzlehttp/psr7 для работы с запросами и ответами:
composer require guzzlehttp/psr7
Шаг 2: Структура проекта
Создайте следующую структуру файлов:
index.php— точка входа в приложениеschema.graphql— файл с определением схемы GraphQLresolvers.php— файл с функциями-резолверамиdata.php— имитация базы данных (массив с данными)
Определение схемы GraphQL
Шаг 3: Написание схемы
Схема — это описание типов данных и доступных операций (запросы и мутации). Создадим простую схему для управления списком книг. Откройте файл schema.graphql и вставьте следующий код:
type Book {
id: ID!
title: String!
author: String!
year: Int
}
type Query {
books: [Book]
book(id: ID!): Book
}
type Mutation {
addBook(title: String!, author: String!, year: Int): Book
deleteBook(id: ID!): Book
}
Здесь мы определили:
- Book — тип данных с полями id, title, author и year.
- Query — операции для получения данных: список всех книг и книга по ID.
- Mutation — операции для изменения данных: добавление и удаление книги.
Шаг 4: Подготовка данных и резолверов
Создайте файл data.php с массивом книг:
<?php
$books = [
1 => ['id' => 1, 'title' => 'Война и мир', 'author' => 'Лев Толстой', 'year' => 1869],
2 => ['id' => 2, 'title' => 'Преступление и наказание', 'author' => 'Фёдор Достоевский', 'year' => 1866],
];
Теперь напишем резолверы в файле resolvers.php. Резолверы — это функции, которые возвращают данные для каждого поля схемы.
<?php
require 'data.php';
function resolveBooks() {
global $books;
return array_values($books);
}
function resolveBook($root, $args) {
global $books;
return $books[$args['id']] ?? null;
}
function resolveAddBook($root, $args) {
global $books;
$newId = count($books) + 1;
$newBook = [
'id' => $newId,
'title' => $args['title'],
'author' => $args['author'],
'year' => $args['year'] ?? null
];
$books[$newId] = $newBook;
return $newBook;
}
function resolveDeleteBook($root, $args) {
global $books;
$book = $books[$args['id']] ?? null;
if ($book) {
unset($books[$args['id']]);
}
return $book;
}
Объединение схемы и резолверов в сервере
Шаг 5: Создание точки входа (index.php)
Теперь соединим всё вместе. В файле index.php мы создадим GraphQL-сервер, который будет принимать HTTP-запросы, обрабатывать их и возвращать ответы.
<?php
require 'vendor/autoload.php';
require 'resolvers.php';
use GraphQL\GraphQL;
use GraphQL\Utils\BuildSchema;
use Psr\Http\Message\ServerRequestInterface;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\ServerRequest;
// Загружаем схему из файла
$schemaContent = file_get_contents('schema.graphql');
$schema = BuildSchema::build($schemaContent);
// Создаем маппинг резолверов
$rootValue = [
'books' => 'resolveBooks',
'book' => 'resolveBook',
'addBook' => 'resolveAddBook',
'deleteBook' => 'resolveDeleteBook',
];
// Обрабатываем входящий запрос
$request = ServerRequest::fromGlobals();
$body = (string) $request->getBody();
$input = json_decode($body, true);
$query = $input['query'];
$variables = $input['variables'] ?? null;
try {
// Выполняем запрос
$result = GraphQL::executeQuery(
$schema,
$query,
$rootValue,
null,
$variables
);
$output = $result->toArray();
} catch (\Exception $e) {
$output = ['errors' => [['message' => $e->getMessage()]]];
}
// Отправляем ответ
$response = new Response(200, ['Content-Type' => 'application/json'], json_encode($output));
// В реальном приложении здесь нужно отправить response через эмиттер PSR-7
echo $response->getBody();
Шаг 6: Запуск и тестирование
Запустите встроенный PHP-сервер:
php -S localhost:8000 index.php
Теперь вы можете отправлять GraphQL-