Swagger-PHP для PHP: полное руководство с примерами
1. Что это и зачем нужна
Swagger-PHP — это мощная библиотека для языка PHP, которая позволяет автоматически генерировать OpenAPI (ранее Swagger) спецификацию вашего REST API на основе аннотаций в коде. Вместо того чтобы вручную писать огромные YAML или JSON файлы с описанием всех эндпоинтов, параметров, моделей данных и ответов, вы просто добавляете специальные комментарии (аннотации) прямо в контроллеры, модели и маршруты вашего PHP-приложения. Библиотека анализирует эти аннотации и создает полную, валидную OpenAPI спецификацию, которую можно экспортировать в формате JSON или YAML.
Зачем это нужно? В современной веб-разработке API является ключевым интерфейсом взаимодействия между фронтендом, мобильными приложениями и сторонними сервисами. Поддержка документации в актуальном состоянии — это постоянная головная боль. Swagger-PHP решает эту проблему, связывая документацию напрямую с исходным кодом. Если вы меняете логику эндпоинта, вы меняете и аннотацию рядом с ним. Документация всегда соответствует реальному поведению API. Это экономит часы работы, уменьшает количество ошибок интеграции и делает ваш проект прозрачным для новых разработчиков.
Кроме того, сгенерированную OpenAPI спецификацию можно использовать с десятками инструментов: Swagger UI (интерактивная документация, где можно тестировать запросы прямо из браузера), генераторы клиентских SDK для JavaScript, Python, Java и других языков, инструменты для тестирования и валидации (например, Postman или Insomnia), а также для автоматической генерации мок-серверов. Swagger-PHP — это стандарт де-факто для документирования PHP API.
2. Установка
Установка производится через Composer — стандартный менеджер пакетов для PHP. Выполните следующую команду в корне вашего проекта:
composer require zircote/swagger-php
После установки в вашем проекте появится директория vendor/zircote/swagger-php. Библиотека требует PHP версии 8.0 или выше (для поддержки современных аннотаций PHP 8 атрибутов). Если вы используете более старую версию PHP, вам потребуется версия библиотеки 3.x, но настоятельно рекомендуется перейти на PHP 8+ и использовать последнюю версию Swagger-PHP (4.x).
3. Быстрый старт — минимальный рабочий пример
Давайте создадим простейший контроллер с одним эндпоинтом и сгенерируем для него OpenAPI спецификацию.
Шаг 1: Создайте файл src/Controllers/UserController.php
<?php
namespace App\Controllers;
use OpenApi\Attributes as OA;
class UserController
{
#[OA\Get(
path: '/api/users/{id}',
summary: 'Получить пользователя по ID',
tags: ['Users']
)]
#[OA\Parameter(
name: 'id',
in: 'path',
required: true,
schema: new OA\Schema(type: 'integer')
)]
#[OA\Response(
response: 200,
description: 'Успешный ответ',
content: new OA\JsonContent(
properties: [
new OA\Property(property: 'id', type: 'integer'),
new OA\Property(property: 'name', type: 'string'),
new OA\Property(property: 'email', type: 'string')
]
)
)]
public function getUser(int $id): array
{
// Здесь должна быть логика получения пользователя из БД
return [
'id' => $id,
'name' => 'John Doe',
'email' => 'john@example.com'
];
}
}
Шаг 2: Создайте скрипт для генерации спецификации generate-docs.php
<?php
require_once __DIR__ . '/vendor/autoload.php';
use OpenApi\Generator;
// Указываем директорию, где находятся наши контроллеры с аннотациями
$openapi = Generator::scan(['src/Controllers']);
// Сохраняем в файл в формате JSON
$openapi->saveAs('openapi.json');
echo "OpenAPI спецификация сгенерирована в файл openapi.json\n";
Шаг 3: Запустите скрипт
php generate-docs.php
В результате вы получите файл openapi.json, который содержит полную спецификацию вашего API. Вы можете открыть его в Swagger Editor или Swagger UI для визуализации.
4. Основные методы/функции/классы
Swagger-PHP предоставляет богатый набор атрибутов (аннотаций) для описания всех аспектов вашего API. Рассмотрим 8 ключевых из них.
4.1. OpenApi\Attributes\Get (и другие HTTP методы: Post, Put, Delete, Patch)
Сигнатура: new OpenApi\Attributes\Get(string $path, ?string $summary = null, ?string $description = null, array $tags = [], ?array $parameters = null, ?OpenApi\Attributes\Response $response = null, ...)
Что делает: Определяет эндпоинт API для HTTP метода GET. Аналогичные атрибуты существуют для POST, PUT, DELETE, PATCH, OPTIONS, HEAD. Это основной атрибут для описания маршрута.
Рабочий пример кода:
#[OA\Post(
path: '/api/users',
summary: 'Создать нового пользователя',
tags: ['Users']
)]
public function createUser(): array {
// логика создания
return ['status' => 'created'];
}
4.2. OpenApi\Attributes\Parameter
Сигнатура: new OpenApi\Attributes\Parameter(string $name, string $in, bool $required = false, ?OpenApi\Attributes\Schema $schema = null, ?string $description = null)
Что делает: Описывает параметр запроса. Параметр может быть в пути (path), в строке запроса (query), в заголовке (header), в cookie (cookie). Обязательно указывать, где находится параметр.
Рабочий пример кода:
#[OA\Parameter(
name: 'page',
in: 'query',
required: false,
schema: new OA\Schema(type: 'integer', default: 1),
description: 'Номер страницы для пагинации'
)]
4.3. OpenApi\Attributes\Response
Сигнатура: new OpenApi\Attributes\Response(int $response, string $description, ?OpenApi\Attributes\MediaType $content = null, ?array $headers = null)
Что делает: Описывает один возможный ответ от сервера. Вы можете указать HTTP статус-код (200, 404, 500 и т.д.), описание и содержимое ответа (JSON, XML и т.д.).
Рабочий пример кода:
#[OA\Response(
response: 404,
description: 'Пользователь не найден',
content: new OA\JsonContent(
properties: [
new OA\Property(property: 'error', type: 'string')
]
)
)]
4.4. OpenApi\Attributes\Schema
Сигнатура: new OpenApi\Attributes\Schema(string $type = 'object', ?array $properties = null, ?string $ref = null, ?array $required = null, ?string $description = null)
Что делает: Определяет схему данных (модель). Это может быть простой тип (string, integer, boolean) или сложный объект со свойствами. Используется для описания тел запросов и ответов.
Рабочий пример кода:
#[OA\Schema(
schema: 'User',
required: ['name', 'email'],
properties: [
new OA\Property(property: 'name', type: 'string'),
new OA\Property(property: 'email', type: 'string', format: 'email'),
new OA\Property(property: 'age', type: 'integer', nullable: true)
]
)]
4.5. OpenApi\Attributes\Property
Сигнатура: new OpenApi\Attributes\Property(string $property, string $type, ?string $format = null, ?bool $nullable = false, ?string $description = null)
Что делает: Описывает одно свойство внутри объекта Schema. Позволяет задать тип, формат (например, email, date-time, uri), описание и может ли свойство быть null.
Рабочий пример кода:
new OA\Property(
property: 'created_at',
type: 'string',
format: 'date-time',
description: 'Дата и время создания записи'
)
4.6. OpenApi\Attributes\RequestBody
Сигнатура: new OpenApi\Attributes\RequestBody(?string $description = null, bool $required = false, ?OpenApi\Attributes\MediaType $content = null)
Что делает: Описывает тело запроса для POST, PUT, PATCH методов. Содержит описание и контент (обычно JSON).
Рабочий пример кода:
#[OA\RequestBody(
required: true,
content: new OA\JsonContent(
ref: '#/components/schemas/User'
)
)]
4.7. OpenApi\Attributes\Tag
Сигнатура: new OpenApi\Attributes\Tag(string $name, ?string $description = null)
Что делает: Определяет тег для группировки эндпоинтов. Теги используются в Swagger UI для создания разделов в документации. Обычно размещается на уровне класса контроллера.
Рабочий пример кода:
#[OA\Tag(
name: 'Users',
description: 'Операции с пользователями'
)]
class UserController { ... }
4.8. OpenApi\Attributes\SecurityScheme
Сигнатура: new OpenApi\Attributes\SecurityScheme(string $securityScheme, string $type, string $scheme, ?string $bearerFormat = null, ?string $description = null)
Что делает: Описывает схему аутентификации, используемую в API. Поддерживает базовую аутентификацию, Bearer токены (JWT), API ключи и OAuth2.
Рабочий пример кода:
#[OA\SecurityScheme(
securityScheme: 'bearerAuth',
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
description: 'Введите JWT токен в формате: Bearer <token>'
)]
5. Реальный практический пример (100-200 строк кода)
Рассмотрим полноценный пример контроллера для управления задачами (Task Manager) с полной документацией.
<?php
namespace App\Controllers;
use OpenApi\Attributes as OA;
#[OA\Tag(name: 'Tasks', description: 'Управление задачами')]
#[OA\Info(
version: '1.0.0',
title: 'Task Manager API',
description: 'API для управления списком задач'
)]
#[OA\Server(url: 'http://localhost:8000', description: 'Локальный сервер')]
class TaskController
{
private array $tasks = [];
#[OA\Get(
path: '/api/tasks',
summary: 'Получить список всех задач',
tags: ['Tasks']
)]
#[OA\Parameter(
name: 'status',
in: 'query',
required: false,
schema: new OA\Schema(type: 'string', enum: ['todo', 'in_progress', 'done']),
description: 'Фильтр по статусу задачи'
)]
#[OA\Response(
response: 200,
description: 'Список задач',
content: new OA\JsonContent(
type: 'array',
items: new OA\Items(ref: '#/components/schemas/Task')
)
)]
public function index(?string $status = null): array
{
if ($status) {
return array_filter($this->tasks, fn($task) => $task['status'] === $status);
}
return $this->tasks;
}
#[OA\Post(
path: '/api/tasks',
summary: 'Создать новую задачу',
tags: ['Tasks']
)]
#[OA\RequestBody(
required: true,
content: new OA\JsonContent(
required: ['title'],
properties: [
new OA\Property(property: 'title', type: 'string', description: 'Название задачи'),
new OA\Property(property: 'description', type: 'string', description: 'Описание задачи'),
new OA\Property(property: 'priority', type: 'string', enum: ['low', 'medium', 'high'], default: 'medium')
]
)
)]
#[OA\Response(
response: 201,
description: 'Задача создана',
content: new OA\JsonContent(ref: '#/components/schemas/Task')
)]
#[OA\Response(response: 400, description: 'Некорректные данные')]
public function store(array $data): array
{
if (empty($data['title'])) {
http_response_code(400);
return ['error' => 'Название задачи обязательно'];
}
$task = [
'id' => count($this->tasks) + 1,
'title' => $data['title'],
'description' => $data['description'] ?? '',
'priority' => $data['priority'] ?? 'medium',
'status' => 'todo',
'created_at' => date('c')
];
$this->tasks[] = $task;
http_response_code(201);
return $task;
}
#[OA\Get(
path: '/api/tasks/{id}',
summary: 'Получить задачу по ID',
tags: ['Tasks']
)]
#[OA\Parameter(
name: 'id',
in: 'path',
required: true,
schema: new OA\Schema(type: 'integer'),
description: 'ID задачи'
)]
#[OA\Response(
response: 200,
description: 'Данные задачи', Также в библиотеке
openai-api-rs для Rust: полное руководство с примерами
TBB (Intel Threading Building Blocks) для C++: полное руководство с примерами
Парсинг HTML в C# (.NET): библиотеки HtmlAgilityPack и AngleSharp
Криптография в Swift: шифрование и хеширование для iOS/macOS