REST API в Yii2: валидация, ошибки и версии без лишней магии

REST API в Yii2 часто начинается с одного контроллера и пары методов. Потом к нему подключают мобильное приложение, CRM, сайт, склад, партнёров. И внезапно любое изменение ответа становится рискованным: один клиент ждёт поле name, другой уже перешёл на title, третий не понимает новый формат ошибки.

API нужно проектировать так, чтобы его было удобно читать человеку и безопасно использовать внешним системам.

Стабильный формат ответа

Если один метод возвращает объект, другой массив, третий строку ошибки, интеграция быстро становится хрупкой. Лучше договориться о формате.

{
    "success": false,
    "error": {
        "code": "VALIDATION_ERROR",
        "message": "Некорректные данные",
        "fields": {
            "email": ["Email обязателен"]
        }
    }
}

Не обязательно использовать именно такой формат, но он должен быть одинаковым.

HTTP-коды

Не нужно возвращать 200 на любую ошибку. Клиент API должен понимать ситуацию по HTTP-коду и телу ответа.

  • 200 — успешный запрос;
  • 201 — создана новая сущность;
  • 400 — неверный запрос;
  • 401 — нет авторизации;
  • 403 — нет доступа;
  • 404 — сущность не найдена;
  • 422 — ошибка валидации;
  • 429 — слишком много запросов;
  • 500 — внутренняя ошибка сервера.

Валидация через модели

Для входящих данных удобно использовать отдельную form model или DTO, а не валидировать массив прямо в action.

class CreateLeadForm extends \yii\base\Model
{
    public $name;
    public $phone;
    public $email;

    public function rules()
    {
        return [
            [['name', 'phone'], 'required'],
            ['email', 'email'],
            [['name', 'phone', 'email'], 'trim'],
        ];
    }
}

Так правила проверки остаются рядом и не расползаются по контроллеру.

Контроллер не должен делать всё

Action должен принять данные, проверить доступ, вызвать сервис и вернуть ответ. Если внутри action создаётся заказ, списывается остаток, отправляется письмо и вызывается CRM, поддерживать API будет сложно.

public function actionCreate()
{
    $form = new CreateLeadForm();
    $form->load(Yii::$app->request->bodyParams, '');

    if (!$form->validate()) {
        return $this->validationError($form);
    }

    $lead = $this->leadService->createFromApi($form);

    return $this->asJson([
        'id' => $lead->id,
    ]);
}

Версионирование

Если API уже используют внешние клиенты, нельзя менять формат ответа без предупреждения. Для крупных изменений нужна версия.

/api/v1/orders
/api/v2/orders

Мелкие добавления обычно безопасны, если старые поля не удаляются и не меняют смысл. Удаление поля или смена типа — уже риск.

Авторизация

API не должен полагаться только на скрытый URL. Нужна понятная авторизация: Bearer token, OAuth, подпись запроса или другой подход под проект.

Authorization: Bearer <token>

Токены нельзя писать в логи целиком. Достаточно фиксировать, что токен был передан и какой технический пользователь найден.

Rate limit

Даже внутренний API может получить слишком много запросов из-за ошибки интеграции. Rate limit помогает защитить проект от случайного шторма.

429 Too Many Requests

Для партнёрских интеграций лимиты лучше документировать заранее.

Логи API

Для диагностики полезно писать метод, пользователя, IP, request ID, длительность и результат.

[
    'request_id' => 'a1b2c3',
    'method' => 'POST /api/v1/orders',
    'user_id' => 15,
    'status' => 201,
    'duration' => 0.182,
]

Полное тело запроса нужно логировать осторожно. Там могут быть персональные данные и секреты.

Чек-лист

  1. Зафиксировать единый формат успешных ответов и ошибок.
  2. Использовать корректные HTTP-коды.
  3. Вынести валидацию во form model.
  4. Не держать бизнес-логику в action.
  5. Продумать версионирование до первых breaking changes.
  6. Настроить авторизацию.
  7. Добавить rate limit для внешних клиентов.
  8. Логировать request ID, метод, статус и длительность.

Хороший API скучен для интегратора: понятные ошибки, предсказуемые поля, стабильные версии и нормальные коды ответа. Чем меньше сюрпризов в контракте, тем меньше аварий после доработок.

Комментарии (0)

Пока нет комментариев. Будьте первым!