Swagger-PHP для PHP: полное руководство с примерами

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

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

Начать курс

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: 'Данные задачи',                    

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