REST API — не набор контроллеров, которые возвращают JSON. Это контракт между клиентами и сервером: структура ресурсов, правила ошибок, авторизация, повторные запросы, ограничения и совместимость версий.
Первоначальная стать я обещала «полное руководство», но содержала только список общих шагов. В обновлённой версии разберём проектирование рабочего API на современном Laravel. На сентябрь 2026 года актуальная основная ветка — Laravel 13, требующая PHP 8.3 или новее.
Начните с контракта, а не с маршрутов
До написания контроллера определите:
- кто клиент API;
- какие ресурсы доступны;
- какие операции разрешены;
- кто владеет данными;
- какие действия повторяемы;
- какие ответы считаются ошибками;
- как меняется контракт;
- какие ограничения по времени и объёму.
Если мобильное приложение, интеграция 1С и партнёрский кабинет используют одно API, их права и требования могут различаться. Не стоит проектировать всё под первый экран фронтенда.
Модель ресурсов
URL должен описывать сущность, а HTTP-метод — действие над ней:
GET /api/orders— список;POST /api/orders— создание;GET /api/orders/{order}— карточка;PATCH /api/orders/{order}— частичное изменение;DELETE /api/orders/{order}— удаление, если оно допустимо.
Laravel предоставляет Route::apiResource, но генерация маршрутов не освобождает от решения о статусах, фильтрах, пагинации и переходах состояния.
Сложное бизнес-действие можно выразить отдельным endpoint, например подтверждением или отменой заказа. Не нужно притворяться, что любое действие является обычным редактированием поля.
Контроллер не должен содержать весь процесс
Практичная структура:
- Form Request проверяет формат входа;
- Policy отвечает за право выполнить действие;
- сервис или action содержит бизнес-операцию;
- Eloquent model отвечает за данные и отношения;
- API Resource формирует публичный ответ;
- Job выполняет долгую фоновую работу;
- Event сообщает о свершившемся факте.
Тонкий контроллер проще тестировать, а бизнес-операцию можно вызвать из HTTP, очереди или административного сценария без копирования логики.
Валидация и бизнес-правила
Проверка required|string подтверждает только форму. Она не отвечает на вопросы:
- доступен ли товар;
- разрешён ли переход статуса;
- принадлежит ли объект пользователю;
- не истёк ли срок предложения;
- не была ли операция выполнена ранее.
Разделяйте синтаксическую валидацию, авторизацию и доменное правило. Клиент должен получать стабильный код ошибки, понятное сообщение и указание проблемного поля, если оно есть.
API Resources и стабильность ответа
Не возвращайте Eloquent-модель напрямую. Состав полей базы меняется по внутренним причинам и не должен автоматически менять публичный API.
API Resource позволяет:
- переименовать поля;
- скрыть внутренние атрибуты;
- условно добавить отношения;
- унифицировать даты и деньги;
- сохранить обратную совместимость;
- централизовать ссылки и метаданные.
Laravel 13 также развивает first-party JSON:API resources. Выбор обычного JSON или JSON:API зависит от клиентов, но формат должен быть единым во всём продукте.
Аутентификация: Sanctum или Passport
Для собственного SPA, мобильного приложения и простых API-токенов Laravel рекомендует Sanctum. Он поддерживает сессионную аутентификацию first-party SPA и токены с abilities.
Passport нужен, когда действительно требуется полный OAuth2: сторонние клиенты, authorization flow, refresh tokens и делегированный доступ.
Токен подтверждает личность, но не право на конкретный объект. После аутентификации всегда применяйте policies или отдельные проверки доступа.
Авторизация на уровне объекта
Типовая уязвимость: пользователь меняет ID в URL и получает чужой заказ. Route model binding сам по себе не проверяет владельца.
Проверьте:
- принадлежность ресурса;
- роль пользователя;
- организацию или tenant;
- допустимость действия в текущем статусе;
- доступ к вложенным объектам;
- права на экспорт и массовые операции.
Тест должен включать не только разрешённый сценарий, но и попытку обратиться к объекту другого клиента.
Идемпотентность
Мобильная сеть может оборваться после того, как сервер уже создал заказ. Клиент повторит запрос и получит дубль.
Для чувствительных POST используйте idempotency key:
- Клиент генерирует стабильный ключ операции.
- Сервер связывает его с пользователем и endpoint.
- Первый запрос выполняет действие и сохраняет ответ.
- Повтор с тем же телом получает тот же результат.
- Тот же ключ с другим телом отклоняется.
Это особенно важно для оплат, заявок, бронирований и формирования документов.
Rate limiting и защита от злоупотреблений
Лимиты должны учитывать тип endpoint.
- Авторизация защищается от перебора.
- Поиск — от дорогих запросов.
- Загрузка файлов — от объёма и количества.
- Публичная форма — от ботов.
- Партнёрский API — по клиенту или ключу.
Возвращайте 429 Too Many Requests и заголовки, позволяющие понять время повтора. Один глобальный лимит может одновременно мешать нормальным клиентам и не защищать дорогую операцию.
Очереди для долгих действий
Отправка письма, генерация PDF, импорт файла и обращение к медленному внешнему сервису не должны удерживать HTTP-запрос без необходимости.
API может вернуть 202 Accepted, идентификатор операции и endpoint статуса. Для job задаются:
- таймаут;
- количество попыток;
- backoff;
- уникальность или идемпотентность;
- обработка окончательной ошибки;
- correlation ID.
Пользователь должен понимать, что операция принята, выполняется или завершилась ошибкой.
Единый формат ошибок
Ошибка должна быть машинно читаемой. Полезные поля:
- стабильный
code; - сообщение для пользователя;
- ошибки отдельных полей;
- request/correlation ID;
- ссылка на документацию для публичного API.
Стек, SQL, путь к файлу и секреты никогда не возвр ащаются клиенту. В production APP_DEBUG должен быть выключен.
Версионирование
Версия в URL — один из вариантов, но важнее политика совместимости.
Согласуйте:
- что считается breaking change;
- сколько поддерживается старая версия;
- как объявляется прекращение;
- можно ли добавлять необязательные поля;
- как версионируются webhooks;
- как клиент узнаёт о миграции.
Изменение типа поля, удаление значения enum или новый обязательный параметр могут сломать клиента даже без изменения URL.
Документация OpenAPI
Описание должно содержать не только успешный пример. Документируйте:
- схему запроса и ответа;
- способы аутентификации;
- ограничения и пагинацию;
- коды ошибок;
- идемпотентность;
- webhooks;
- примеры по версиям.
Проверяйте OpenAPI в CI и по возможности генерируйте часть документации из тех же схем, которые используются для проверки контракта.
Тестирование API
Минимальный набор feature-тестов:
- успешная операция;
- обязательные и граничные поля;
- пользователь без токена;
- пользователь без права;
- чужой объект;
- повторный idempotency key;
- превышение лимита;
- временная ошибка внешней системы;
- очередь и окончательный сбой;
- соответствие JSON-схеме.
Отдельно проверяйте миграции базы и совместимость с предыдущей версией клиента.
Production-чек-лист
- Используется поддерживаемая версия PHP и Laravel.
APP_DEBUG=false.- Конфигурация, маршруты и события кэшируются при развёртывании.
- Секреты находятся вне репозитория.
- Токены имеют минимальные abilities.
- Policies покрывают доступ к объектам.
- Критические операции идемпотентны.
- Очереди и failed jobs наблюдаются.
- Логи содержат correlation ID, но не персональные данные и токены.
- Документация и контракт проверяются в CI.
Laravel ускоряет реализацию типовых частей, но качество API определяется контрактом и эксплуатационными правилами. В проектах KorDevTeam мы сначала описываем клиентов, данные и сбои, а уже затем выбираем маршруты, ресурсы и пакеты.
Теги: Laravel, PHP, REST API, API Development, Интеграции Дата публикации: 5 октября 2025 Дата обновления: 25 сентября 2026



