Eloquent: API Ресурси

Вступ

Коли ви створюєте API, вам може знадобитися шар трансформації, який знаходиться між вашими моделями Eloquent та JSON-відповідями, що фактично повертаються користувачам вашого застосунку. Наприклад, ви можете захотіти відображати певні атрибути для підмножини користувачів, а не для інших, або ви можете завжди включати певні відносини в JSON-представлення ваших моделей. Ресурсні класи Eloquent дозволяють виразно та легко трансформувати ваші моделі та колекції моделей у JSON.

Звичайно, ви завжди можете конвертувати моделі Eloquent або колекції в JSON, використовуючи їхні методи toJson; однак, ресурси Eloquent надають більш детальний і надійний контроль над JSON-серіалізацією ваших моделей та їхніх відносин.

Генерація Ресурсів

Щоб згенерувати ресурсний клас, ви можете використовувати команду Artisan make:resource. За замовчуванням ресурси будуть розміщені в директорії app/Http/Resources вашого застосунку. Ресурси розширюють клас Illuminate\Http\Resources\Json\JsonResource:

php artisan make:resource UserResource

Колекції ресурсів

Крім генерації ресурсів, які трансформують окремі моделі, ви можете генерувати ресурси, які відповідають за трансформацію колекцій моделей. Це дозволяє вашим JSON-відповідям включати посилання та іншу метаінформацію, яка стосується всієї колекції даного ресурсу.

Щоб створити колекцію ресурсів, ви повинні використовувати прапорець --collection при створенні ресурсу. Або, включення слова Collection в назву ресурсу вкаже Laravel, що він повинен створити ресурс колекції. Ресурси колекцій розширюють клас Illuminate\Http\Resources\Json\ResourceCollection:

php artisan make:resource User --collection
 
php artisan make:resource UserCollection

Огляд концепції

Це огляд на високому рівні ресурсів і колекцій ресурсів. Вам настійно рекомендується прочитати інші розділи цієї документації, щоб отримати глибше розуміння налаштувань і можливостей, які надаються вам ресурсами.

Перш ніж зануритися в усі доступні вам опції при написанні ресурсів, давайте спочатку розглянемо на високому рівні, як ресурси використовуються в Laravel. Клас ресурсу представляє одну модель, яку потрібно перетворити в структуру JSON. Наприклад, ось простий клас ресурсу UserResource:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
 
class UserResource extends JsonResource
{
/**
* Перетворити ресурс на масив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}

Кожен клас ресурсу визначає метод toArray, який повертає масив атрибутів, що повинні бути перетворені в JSON, коли ресурс повертається як відповідь з маршруту або методу контролера.

Зверніть увагу, що ми можемо отримати доступ до властивостей моделі безпосередньо з змінної $this. Це тому, що клас ресурсу автоматично проксіює доступ до властивостей і методів до базової моделі для зручного доступу. Після визначення ресурсу його можна повернути з маршруту або контролера. Ресурс приймає екземпляр базової моделі через свій конструктор:

use App\Http\Resources\UserResource;
use App\Models\User;
 
Route::get('/user/{id}', function (string $id) {
    return new UserResource(User::findOrFail($id));
});

Для зручності, ви можете використовувати метод моделі toResource, який буде використовувати конвенції фреймворку для автоматичного виявлення базового ресурсу моделі:

return User::findOrFail($id)->toResource();

Коли викликається метод toResource, Laravel спробує знайти ресурс, що відповідає імені моделі і, за бажанням, має суфікс Resource у просторі імен Http\Resources, найближчому до простору імен моделі.

Колекції ресурсів

Якщо ви повертаєте колекцію ресурсів або відповідь з пагінацією, ви повинні використовувати метод collection, наданий вашим класом ресурсу, при створенні екземпляра ресурсу у вашому маршруті або контролері:

use App\Http\Resources\UserResource;
use App\Models\User;
 
Route::get('/users', function () {
    return UserResource::collection(User::all());
});

Або, для зручності, ви можете використовувати метод toResourceCollection колекції Eloquent, який буде використовувати конвенції фреймворку для автоматичного виявлення базової колекції ресурсів моделі:

return User::all()->toResourceCollection();

Коли викликається метод toResourceCollection, Laravel спробує знайти колекцію ресурсів, яка відповідає назві моделі та має суфікс Collection у просторі імен Http\Resources, найближчому до простору імен моделі.

Користувацькі Колекції ресурсів

За замовчуванням, колекції ресурсів не дозволяють додавати жодних додаткових метаданих, які можуть знадобитися для повернення разом з вашою колекцією. Якщо ви хочете налаштувати відповідь колекції ресурсів, ви можете створити спеціальний ресурс для представлення колекції:

php artisan make:resource UserCollection

Після того, як клас колекції ресурсів було згенеровано, ви можете легко визначити будь-які метадані, які слід включити у відповідь:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;
 
class UserCollection extends ResourceCollection
{
    /**
     * Перетворіть колекцію ресурсів у масив.
     *
     * @return array<int|string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'data' => $this->collection,
            'links' => [
                'self' => 'link-value',
            ],
        ];
    }
}

Після визначення вашої колекції ресурсів, її можна повернути з маршруту або контролера:

use App\Http\Resources\UserCollection;
use App\Models\User;
 
Route::get('/users', function () {
    return new UserCollection(User::all());
});

Або, для зручності, ви можете скористатися методом toResourceCollection колекції Eloquent, який використовуватиме конвенції фреймворку для автоматичного виявлення базової колекції ресурсів моделі:

return User::all()->toResourceCollection();

Коли викликається метод toResourceCollection, Laravel спробує знайти колекцію ресурсів, яка відповідає назві моделі і має суфікс Collection у просторі імен Http\Resources, найближчому до простору імен моделі.

Збереження Ключів Колекції

Коли повертається колекція ресурсів з маршруту, Laravel скидає ключі колекції, щоб вони були в числовому порядку. Однак, ви можете додати властивість preserveKeys до вашого класу ресурсу, вказуючи, чи повинні зберігатися оригінальні ключі колекції:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Resources\Json\JsonResource;
 
class UserResource extends JsonResource
{
    /**
     * Вказує, чи слід зберігати ключі колекції ресурсу.
     *
     * @var bool
     */
    public $preserveKeys = true;
}

Коли властивість preserveKeys встановлена в true, ключі колекції будуть збережені, коли колекція повертається з маршруту або контролера:

use App\Http\Resources\UserResource;
use App\Models\User;
 
Route::get('/users', function () {
    return UserResource::collection(User::all()->keyBy->id);
});

Налаштування Базового Класу Ресурсу

Зазвичай властивість $this->collection колекції ресурсів автоматично заповнюється результатом відображення кожного елемента колекції на його одиничний клас ресурсу. Одиничний клас ресурсу вважається ім'ям класу колекції без кінцевої частини Collection в імені класу. Крім того, залежно від ваших особистих уподобань, одиничний клас ресурсу може або не може мати суфікс Resource.

Наприклад, UserCollection спробує відобразити надані екземпляри користувачів у ресурс UserResource. Щоб налаштувати цю поведінку, ви можете перевизначити властивість $collects вашої колекції ресурсів:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Resources\Json\ResourceCollection;
 
class UserCollection extends ResourceCollection
{
    /**
     * Ресурс, який збирає цей ресурс.
     *
     * @var string
     */
    public $collects = Member::class;
}

Створення ресурсів

Якщо ви не прочитали огляд концепції, настійно рекомендується зробити це перед тим, як продовжити з цією документацією.

Ресурси лише потребують перетворити дану модель у масив. Отже, кожен ресурс містить метод toArray, який перетворює атрибути вашої моделі у масив, зручний для API, який може бути повернутий з маршрутів або контролерів вашого застосунку:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
 
class UserResource extends JsonResource
{
    /**
     * Перетворити ресурс у масив.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

Як тільки ресурс визначено, його можна повернути безпосередньо з маршруту або контролера:

use App\Models\User;
 
Route::get('/user/{id}', function (string $id) {
    return User::findOrFail($id)->toUserResource();
});

Відносини

Якщо ви хочете включити пов'язані ресурси у вашу відповідь, ви можете додати їх до масиву, що повертається методом toArray вашого ресурсу. У цьому прикладі ми використаємо метод collection ресурсу PostResource, щоб додати блоги користувача до відповіді ресурсу:

use App\Http\Resources\PostResource;
use Illuminate\Http\Request;
 
/**
 * Перетворити ресурс у масив.
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'posts' => PostResource::collection($this->posts),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

Якщо ви хочете включити відносини лише тоді, коли вони вже завантажені, ознайомтеся з документацією про умовні відносини.

Колекції ресурсів

Хоча ресурси перетворюють одну модель у масив, колекції ресурсів перетворюють колекцію моделей у масив. Однак, не є абсолютно необхідним визначати клас колекції ресурсів для кожної з ваших моделей, оскільки всі колекції моделей Eloquent надають метод toResourceCollection для створення "ad-hoc" колекції ресурсів на льоту:

use App\Models\User;
 
Route::get('/users', function () {
    return User::all()->toResourceCollection();
});

Однак, якщо вам потрібно налаштувати метадані, що повертаються разом із колекцією, необхідно визначити власну ресурсну колекцію:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;
 
class UserCollection extends ResourceCollection
{
    /**
     * Перетворіть колекцію ресурсів у масив.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'data' => $this->collection,
            'links' => [
                'self' => 'link-value',
            ],
        ];
    }
}

Як і окремі ресурси, колекції ресурсів можуть бути повернені безпосередньо з маршрутів або контролерів:

use App\Http\Resources\UserCollection;
use App\Models\User;
 
Route::get('/users', function () {
    return new UserCollection(User::all());
});

Або, для зручності, ви можете використовувати метод toResourceCollection колекції Eloquent, який буде використовувати конвенції фреймворку для автоматичного виявлення базової колекції ресурсів моделі:

return User::all()->toResourceCollection();

Коли викликається метод toResourceCollection, Laravel спробує знайти колекцію ресурсів, яка відповідає назві моделі і має суфікс Collection у просторі імен Http\Resources, найближчому до простору імен моделі.

Обгортання даних

За замовчуванням ваш найзовнішній ресурс обгорнутий у ключ data, коли відповідь ресурсу перетворюється на JSON. Отже, наприклад, типовий відповідь колекції ресурсів виглядає наступним чином:

{
    "data": [
        {
            "id": 1,
            "name": "Eladio Schroeder Sr.",
            "email": "example@example.com"
        },
        {
            "id": 2,
            "name": "Liliana Mayert",
            "email": "example@example.com"
        }
    ]
}

Якщо ви хочете вимкнути обгортання найзовнішнього ресурсу, ви повинні викликати метод withoutWrapping у базовому класі Illuminate\Http\Resources\Json\JsonResource. Зазвичай, ви повинні викликати цей метод з вашого AppServiceProvider або іншого сервіс-провайдера, який завантажується при кожному запиті до вашого застосунку:

<?php
 
namespace App\Providers;
 
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\ServiceProvider;
 
class AppServiceProvider extends ServiceProvider
{
    /**
     * Зареєструйте будь-які сервіси застосунку.
     */
    public function register(): void
    {
        // ...
    }
 
    /**
     * Завантажте будь-які сервіси застосунку.
     */
    public function boot(): void
    {
        JsonResource::withoutWrapping();
    }
}

Метод withoutWrapping впливає лише на найзовнішню відповідь і не видалить ключі data, які ви вручну додаєте до своїх власних колекцій ресурсів.

Обгортання вкладених ресурсів

Ви маєте повну свободу визначати, як будуть обгорнуті відносини вашого ресурсу. Якщо ви хочете, щоб всі колекції ресурсів були обгорнуті в ключ data, незалежно від їх вкладеності, ви повинні визначити клас колекції ресурсів для кожного ресурсу і повертати колекцію в межах ключа data.

Ви можете запитувати себе, чи не призведе це до того, що ваш найзовнішній ресурс буде обгорнутий у два ключі data. Не хвилюйтеся, Laravel ніколи не дозволить вашим ресурсам бути випадково подвійно обгорнутими, тому вам не потрібно турбуватися про рівень вкладеності колекції ресурсів, яку ви трансформуєте:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Resources\Json\ResourceCollection;
 
class CommentsCollection extends ResourceCollection
{
    /**
     * Перетворіть колекцію ресурсів у масив.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return ['data' => $this->collection];
    }
}

Обгортання даних та пагінація

Коли повертаєте пагіновані колекції через ресурсний відповідь, Laravel обгорне ваші ресурсні дані в ключ data, навіть якщо метод withoutWrapping був викликаний. Це тому, що пагіновані відповіді завжди містять ключі meta та links з інформацією про стан пагінатора:

{
    "data": [
        {
            "id": 1,
            "name": "Eladio Schroeder Sr.",
            "email": "example@example.com"
        },
        {
            "id": 2,
            "name": "Liliana Mayert",
            "email": "example@example.com"
        }
    ],
    "links":{
        "first": "http://example.com/users?page=1",
        "last": "http://example.com/users?page=1",
        "prev": null,
        "next": null
    },
    "meta":{
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://example.com/users",
        "per_page": 15,
        "to": 10,
        "total": 10
    }
}

Пагінація

Ви можете передати екземпляр пагінатора Laravel до методу collection ресурсу або до колекції користувацьких ресурсів:

use App\Http\Resources\UserCollection;
use App\Models\User;
 
Route::get('/users', function () {
    return new UserCollection(User::paginate());
});

Або, для зручності, ви можете використовувати метод пагінатора toResourceCollection, який буде використовувати конвенції фреймворку для автоматичного виявлення базової колекції ресурсів пагінованої моделі:

return User::paginate()->toResourceCollection();

Пагіновані відповіді завжди містять ключі meta та links з інформацією про стан пагінатора:

{
    "data": [
        {
            "id": 1,
            "name": "Eladio Schroeder Sr.",
            "email": "example@example.com"
        },
        {
            "id": 2,
            "name": "Liliana Mayert",
            "email": "example@example.com"
        }
    ],
    "links":{
        "first": "http://example.com/users?page=1",
        "last": "http://example.com/users?page=1",
        "prev": null,
        "next": null
    },
    "meta":{
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://example.com/users",
        "per_page": 15,
        "to": 10,
        "total": 10
    }
}

Налаштування інформації про пагінацію

Якщо ви хочете налаштувати інформацію, включену в ключі links або meta відповіді пагінації, ви можете визначити метод paginationInformation у ресурсі. Цей метод отримає дані $paginated та масив $default інформації, який містить ключі links та meta:

/**
 * Налаштуйте інформацію про пагінацію для ресурсу.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  array $paginated
 * @param  array $default
 * @return array
 */
public function paginationInformation($request, $paginated, $default)
{
    $default['links']['custom'] = 'https://example.com';
 
    return $default;
}

Умовні Атрибути

Іноді ви можете захотіти включити атрибут у відповідь ресурсу лише за умови виконання певної умови. Наприклад, ви можете захотіти включити значення лише якщо поточний користувач є "адміністратором". Laravel надає різноманітні допоміжні методи, щоб допомогти вам у цій ситуації. Метод when може бути використаний для умовного додавання атрибуту до відповіді ресурсу:

/**
 * Перетворити ресурс у масив.
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'secret' => $this->when($request->user()->isAdmin(), 'secret-value'),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

У цьому прикладі ключ secret буде повернуто у фінальному відповіді ресурсу лише якщо метод isAdmin автентифікованого користувача повертає true. Якщо метод повертає false, ключ secret буде видалено з відповіді ресурсу перед тим, як вона буде відправлена клієнту. Метод when дозволяє виразно визначати ваші ресурси без використання умовних інструкцій при побудові масиву.

Метод when також приймає замикання як другий аргумент, що дозволяє обчислити результативне значення лише якщо задана умова є true:

'secret' => $this->when($request->user()->isAdmin(), function () {
    return 'secret-value';
}),

Метод whenHas може бути використаний для включення атрибута, якщо він дійсно присутній у базовій моделі:

'name' => $this->whenHas('name'),

Крім того, метод whenNotNull може бути використаний для включення атрибута у відповідь ресурсу, якщо атрибут не є null:

'name' => $this->whenNotNull($this->name),

Об'єднання Умовних Атрибутів

Іноді у вас може бути кілька атрибутів, які слід включити у відповідь ресурсу лише за певної умови. У цьому випадку ви можете використовувати метод mergeWhen, щоб включити атрибути у відповідь лише тоді, коли задана умова є true:

/**
 * Перетворити ресурс у масив.
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        $this->mergeWhen($request->user()->isAdmin(), [
            'first-secret' => 'value',
            'second-secret' => 'value',
        ]),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

Знову ж таки, якщо задана умова є false, ці атрибути будуть видалені з відповіді ресурсу перед тим, як вона буде відправлена клієнту.

Метод mergeWhen не слід використовувати в масивах, які змішують рядкові та числові ключі. Крім того, його не слід використовувати в масивах з числовими ключами, які не впорядковані послідовно.

Умовні Відносини

Крім умовного завантаження атрибутів, ви можете умовно включати відносини у ваші відповіді ресурсу на основі того, чи вже завантажено відношення на моделі. Це дозволяє вашому контролеру вирішувати, які відносини повинні бути завантажені на моделі, і ваш ресурс може легко включати їх лише тоді, коли вони фактично завантажені. Зрештою, це полегшує уникнення проблеми "N+1" запитів у ваших ресурсах.

Метод whenLoaded може бути використаний для умовного завантаження відношення. Щоб уникнути непотрібного завантаження відношень, цей метод приймає назву відношення замість самого відношення:

use App\Http\Resources\PostResource;
 
/**
 * Перетворити ресурс у масив.
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'posts' => PostResource::collection($this->whenLoaded('posts')),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

У цьому прикладі, якщо відношення не було завантажено, ключ posts буде видалено з відповіді ресурсу перед тим, як вона буде відправлена клієнту.

Умовний підрахунок відносин

Крім умовного включення відносин, ви можете умовно включати "кількість" відносин у ваших відповідях ресурсу, якщо кількість відносин була завантажена на модель:

new UserResource($user->loadCount('posts'));

Метод whenCounted може бути використаний для умовного включення кількості відносин у вашій відповіді ресурсу. Цей метод уникає непотрібного включення атрибута, якщо кількість відносин не присутня:

/**
 * Перетворити ресурс у масив.
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'posts_count' => $this->whenCounted('posts'),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

У цьому прикладі, якщо кількість відношень posts не була завантажена, ключ posts_count буде видалено з відповіді ресурсу перед тим, як вона буде відправлена клієнту.

Інші типи агрегатів, такі як avg, sum, min і max, також можуть бути умовно завантажені за допомогою методу whenAggregated:

'words_avg' => $this->whenAggregated('posts', 'words', 'avg'),
'words_sum' => $this->whenAggregated('posts', 'words', 'sum'),
'words_min' => $this->whenAggregated('posts', 'words', 'min'),
'words_max' => $this->whenAggregated('posts', 'words', 'max'),

Умовна Інформація Повороту

На додаток до умовного включення інформації про відносини у ваших відповідях ресурсу, ви можете умовно включати дані з проміжних таблиць багатобагатьох відносин, використовуючи метод whenPivotLoaded. Метод whenPivotLoaded приймає назву з'єднувальної таблиці як свій перший аргумент. Другий аргумент повинен бути замиканням, яке повертає значення, що буде повернено, якщо інформація про з'єднання доступна в моделі:

/**
 * Перетворити ресурс у масив.
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'expires_at' => $this->whenPivotLoaded('role_user', function () {
            return $this->pivot->expires_at;
        }),
    ];
}

Якщо ваш зв'язок використовує модель проміжної таблиці, ви можете передати екземпляр моделі проміжної таблиці як перший аргумент методу whenPivotLoaded:

'expires_at' => $this->whenPivotLoaded(new Membership, function () {
    return $this->pivot->expires_at;
}),

Якщо ваша проміжна таблиця використовує аксесор, відмінний від pivot, ви можете використовувати метод whenPivotLoadedAs:

/**
 * Перетворити ресурс у масив.
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'expires_at' => $this->whenPivotLoadedAs('subscription', 'role_user', function () {
            return $this->subscription->expires_at;
        }),
    ];
}

Додавання Мета Даних

Деякі стандарти JSON API вимагають додавання мета-даних до відповідей ваших ресурсів та колекцій ресурсів. Це часто включає такі речі, як links до ресурсу або пов'язаних ресурсів, або мета-дані про сам ресурс. Якщо вам потрібно повернути додаткові мета-дані про ресурс, включіть їх у ваш метод toArray. Наприклад, ви можете включити інформацію про links при трансформації колекції ресурсів:

/**
 * Перетворити ресурс у масив.
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'data' => $this->collection,
        'links' => [
            'self' => 'link-value',
        ],
    ];
}

Коли ви повертаєте додаткові метадані з ваших ресурсів, вам ніколи не потрібно турбуватися про випадкове перевизначення ключів links або meta, які автоматично додаються Laravel при поверненні пагінованих відповідей. Будь-які додаткові links, які ви визначите, будуть об'єднані з посиланнями, наданими пагінатором.

Верхній рівень метаданих

Іноді ви можете захотіти включити певні метадані до відповіді ресурсу лише якщо ресурс є найзовнішнім ресурсом, що повертається. Зазвичай це включає метаінформацію про відповідь в цілому. Щоб визначити ці метадані, додайте метод with до вашого класу ресурсу. Цей метод повинен повертати масив метаданих, які будуть включені до відповіді ресурсу лише коли ресурс є найзовнішнім ресурсом, що трансформується:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Resources\Json\ResourceCollection;
 
class UserCollection extends ResourceCollection
{
    /**
     * Перетворіть колекцію ресурсів у масив.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return parent::toArray($request);
    }
 
    /**
     * Отримати додаткові дані, які повинні бути повернені з масивом ресурсу.
     *
     * @return array<string, mixed>
     */
    public function with(Request $request): array
    {
        return [
            'meta' => [
                'key' => 'value',
            ],
        ];
    }
}

Додавання Мета Даних під час Конструювання Ресурсів

Ви також можете додати дані верхнього рівня при створенні екземплярів ресурсів у вашому маршруті або контролері. Метод additional, який доступний для всіх ресурсів, приймає масив даних, які слід додати до відповіді ресурсу:

return User::all()
    ->load('roles')
    ->toResourceCollection()
    ->additional(['meta' => [
        'key' => 'value',
    ]]);

Відповіді Ресурсів

Як ви вже читали, ресурси можуть бути повернені безпосередньо з маршрутів і контролерів:

use App\Models\User;
 
Route::get('/user/{id}', function (string $id) {
    return User::findOrFail($id)->toResource();
});

Однак іноді вам може знадобитися налаштувати вихідний HTTP-відповідь перед тим, як вона буде відправлена клієнту. Існує два способи досягти цього. По-перше, ви можете приєднати метод response до ресурсу. Цей метод поверне екземпляр Illuminate\Http\JsonResponse, надаючи вам повний контроль над заголовками відповіді:

use App\Http\Resources\UserResource;
use App\Models\User;
 
Route::get('/user', function () {
    return User::find(1)
        ->toResource()
        ->response()
        ->header('X-Value', 'True');
});

Альтернативно, ви можете визначити метод withResponse безпосередньо в ресурсі. Цей метод буде викликано, коли ресурс повертається як найзовнішній ресурс у відповіді:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
 
class UserResource extends JsonResource
{
    /**
     * Перетворити ресурс у масив.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
        ];
    }
 
    /**
     * Налаштуйте вихідну відповідь для ресурсу.
     */
    public function withResponse(Request $request, JsonResponse $response): void
    {
        $response->header('X-Value', 'True');
    }
}