Как я проектирую API на Laravel под фронт на Vue/React

Когда Laravel стоит за SPA на Vue/React, всё упирается в то, насколько удобно жить фронту. Если API сделан «на автомате», проект быстро превращается в хаос: разные форматы ответов, странные коды ошибок, пляски с авторизацией.

Расскажу, какие правила я закладываю в API сразу, чтобы фронт не страдал.

1. Единый формат ответов

Я договариваюсь так:

  • успешный ответ с данными:

{ "data": {...}, "meta": {...} }

  • ошибка валидации: 422 и объект errors по полям
  • другие ошибки: код по делу (401/403/404/500) и message для фронта

В Laravel это удобно делать через JsonResource и кастомный обработчик исключений, чтобы не плодить return response()->json(...) в каждом контроллере.

2. FormRequest везде, где есть входные данные

Никаких request()->validate() в контроллере, только отдельные классы:

class StorePostRequest extends FormRequest { public function rules(): array { return [ 'title' => ['required','string','max:255'], 'body' => ['required','string'], ]; } }

Плюсы:

  • фронт всегда получает одинаковый формат 422 с ошибками по полям
  • можно переиспользовать правила между эндпоинтами
  • в контроллере остаётся минимум кода

3. Resources вместо «голых» моделей

Я никогда не отдаю модели как есть:

return new PostResource($post);

class PostResource extends JsonResource { public function toArray($request): array { return [ 'id' => $this->id, 'title' => $this->title, 'body' => $this->body, 'author' => [ 'id' => $this->author->id, 'name' => $this->author->name, ], 'created' => $this->created_at->toIso8601String(), ]; } }

Так я могу:

  • переименовывать поля без ломки базы
  • добавлять вычисляемые свойства
  • не светить лишнее (служебные поля, флаги и т.п.)

4. Чёткие URL и действия

Стараюсь держаться REST, без экзотики:

  • список: GET /api/v1/posts
  • элемент: GET /api/v1/posts/{id}
  • создание: POST /api/v1/posts
  • обновление: PUT/PATCH /api/v1/posts/{id}
  • удаление: DELETE /api/v1/posts/{id}

В Laravel это шикарно ложится на Route::apiResource(). Если нужна нестандартная операция (например, публикация), делаю что-то вроде:

POST /api/v1/posts/{id}/publish

а не загадочный POST /api/v1/publishPost.

5. Авторизация для SPA

Чаще всего использую Sanctum:

  • фронт логинится → получает cookie-токен
  • дальше просто шлёт запросы с withCredentials
  • на бэке всё через auth:sanctum

Главное — договориться, какие маршруты публичные, а какие требуют авторизации, и не тащить логику прав на фронт. Фронт только реагирует на 401/403.

6. Мета и пагинация

Для списков я всегда возвращаю:

{ "data": [ ... ], "meta": { "current_page": 1, "per_page": 20, "total": 135 } }

В Laravel это делается через пагинатор и Resource::collection($paginator). Фронту не нужно изобретать свои счётчики страниц и гадать, есть ли ещё данные.

7. Чек-лист перед тем, как отдавать API фронту

  • Все маршруты живут под /api/v1, нет «случайных» урлов
  • Все входные данные валидируются через FormRequest
  • Ответы завернуты в Resources, модели наружу не торчат
  • Формат ошибок единый, есть 422 с ошибками по полям
  • Продумана аутентификация (обычно Sanctum) и роли
  • Пагинация возвращает meta, фронт не гадает про страницы

Итог

Хороший API для Vue/React на Laravel — это не «магический» код, а набор скучных, но понятных правил: единый формат ответов, FormRequest, Resources, аккуратные URL и нормальная авторизация. Когда это заложено, фронту становится всё равно, на чём бэк, а вам проще менять внутренности, не ломая клиент.

#laravel #api #vuejs #reactjs

Как я проектирую API на Laravel под фронт на Vue/React
Когда Laravel стоит за SPA на Vue/React, всё упирается в то, насколько удобно жить фронту | Сетка — социальная сеть от hh.ru