Урок 03

API-ресурсы

Resource — это класс, который преобразует модель в массив для JSON-ответа. Он отделяет структуру API от структуры БД.

Зачем нужны ресурсы

Если возвращать модель напрямую, в JSON попадут все колонки, включая служебные. Ресурс позволяет:

  • выбрать нужные поля
  • переименовать ключи
  • добавить вычисляемые поля
  • вложить связи
  • скрыть敏感ные данные

Создание

php artisan make:resource PostResource

Файл app/Http/Resources/PostResource.php.

Базовый ресурс

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class PostResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'slug' => $this->slug,
            'body' => $this->body,
            'published_at' => $this->published_at?->toISOString(),
            'created_at' => $this->created_at->toISOString(),
        ];
    }
}

Использование в контроллере

public function show(Post $post): PostResource
{
    return new PostResource($post);
}

Коллекция

public function index()
{
    return PostResource::collection(Post::paginate(15));
}

Обёртка data

По умолчанию Laravel оборачивает ответ в data:

{
    "data": {
        "id": 1,
        "title": "..."
    }
}

Отключить обёртку:

// AppServiceProvider::boot()
JsonResource::withoutWrapping();

Условные поля

return [
    'id' => $this->id,
    'title' => $this->title,
    'email' => $this->when($request->user()?->isAdmin(), $this->email),
    'secret' => $this->when($request->user()?->isAdmin(), 'hidden'),
];

whenLoaded

Поле появляется только если связь загружена:

return [
    'id' => $this->id,
    'title' => $this->title,
    'user' => new UserResource($this->whenLoaded('user')),
    'comments' => CommentResource::collection($this->whenLoaded('comments')),
];

whenCounted

return [
    'id' => $this->id,
    'comments_count' => $this->whenCounted('comments'),
];

Если в контроллере был withCount('comments'), поле появится.

Метаданные

public function with(Request $request): array
{
    return [
        'meta' => [
            'version' => '1.0',
            'generated_at' => now()->toISOString(),
        ],
    ];
}