Класс ResourceCollection
Класс ResourceCollection наследуется от JsonResource и предназначен для формирования ответов при работе с коллекциями моделей Eloquent. Он автоматически применяет ресурс к каждому элементу коллекции, позволяя единообразно форматировать данные. Основное преимущество использования ResourceCollection заключается в возможности добавления метаданных, пагинации и дополнительных полей к ответу без изменения логики отдельных ресурсов.
При создании ресурса для коллекции необходимо определить метод toArray, который принимает текущий запрос и возвращает массив данных. В отличие от JsonResource, где метод работает с одной моделью, ResourceCollection работает с коллекцией и предоставляет доступ к методам пагинации через свойство resource, если передана пагинированная коллекция.
Синтаксис
<?php
namespace AppHttpResources;
use IlluminateHttpResourcesJsonResourceCollection;
class UserCollection extends ResourceCollection
{
public function toArray($request)
{
return [
'data' => $this->collection,
'meta' => [
'total' => $this->total(),
'count' => $this->count(),
],
];
}
}
?>
Создание ресурса коллекции
Для создания ресурса коллекции используется Artisan-команда make:resource с флагом --collection. Это сгенерирует класс, наследующий от ResourceCollection:
php artisan make:resource UserCollection --collection
Сгенерированный класс будет расположен в директории app/Http/Resources. Рассмотрим базовую структуру такого класса:
<?php
namespace AppHttpResources;
use IlluminateHttpResourcesJsonResourceCollection;
class UserCollection extends ResourceCollection
{
public function toArray($request)
{
return [
'data' => $this->collection,
];
}
}
?>
Пример с отдельным ресурсом
Создадим ресурс для модели пользователя, который будет использоваться внутри коллекции:
<?php
namespace AppHttpResources;
use IlluminateHttpResourcesJsonJsonResource;
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
];
}
}
?>
Теперь создадим коллекцию, которая будет использовать этот ресурс:
<?php
namespace AppHttpResources;
use IlluminateHttpResourcesJsonResourceCollection;
class UserCollection extends ResourceCollection
{
public $collects = UserResource::class;
public function toArray($request)
{
return [
'data' => $this->collection,
'count' => $this->collection->count(),
];
}
}
?>
Используем коллекцию в контроллере:
<?php
namespace AppHttpControllers;
use AppModelsUser;
use AppHttpResourcesUserCollection;
class UserController extends Controller
{
public function index()
{
$users = User::all();
return new UserCollection($users);
}
}
?>
Результат выполнения кода:
{
"data": [
{
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"created_at": "2024-01-01 12:00:00"
},
{
"id": 2,
"name": "Jane Smith",
"email": "jane@example.com",
"created_at": "2024-01-02 12:00:00"
}
],
"count": 2
}
Работа с пагинацией
ResourceCollection автоматически определяет, является ли переданная коллекция пагинированной, и предоставляет доступ к методам пагинации:
<?php
namespace AppHttpResources;
use IlluminateHttpResourcesJsonResourceCollection;
class PostCollection extends ResourceCollection
{
public function toArray($request)
{
return [
'data' => $this->collection,
'pagination' => [
'total' => $this->total(),
'per_page' => $this->perPage(),
'current_page' => $this->currentPage(),
'last_page' => $this->lastPage(),
],
];
}
}
?>
Использование в контроллере с пагинацией:
<?php
namespace AppHttpControllers;
use AppModelsPost;
use AppHttpResourcesPostCollection;
class PostController extends Controller
{
public function index()
{
$posts = Post::paginate(10);
return new PostCollection($posts);
}
}
?>
Результат выполнения кода:
{
"data": [
{
"id": 1,
"title": "First Post",
"content": "Content of first post"
},
{
"id": 2,
"title": "Second Post",
"content": "Content of second post"
}
],
"pagination": {
"total": 25,
"per_page": 10,
"current_page": 1,
"last_page": 3
}
}
Добавление метаданных
Для добавления метаданных к ответу используется метод with. Это позволяет включать дополнительную информацию, которая не относится непосредственно к данным:
<?php
namespace AppHttpResources;
use IlluminateHttpResourcesJsonResourceCollection;
class ProductCollection extends ResourceCollection
{
public function toArray($request)
{
return [
'data' => $this->collection,
];
}
public function with($request)
{
return [
'meta' => [
'timestamp' => now(),
'version' => '1.0.0',
'total_products' => $this->collection->count(),
],
];
}
}
?>
Условная фильтрация данных
Внутри ресурса коллекции можно применять условную фильтрацию для показа определенных полей только в определенных ситуациях:
<?php
namespace AppHttpResources;
use IlluminateHttpResourcesJsonJsonResource;
class AdminUserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'admin_notes' => $this->when(
$request->user()->isAdmin(),
$this->admin_notes
),
];
}
}
?>
Преобразование без отдельного ресурса
Если не требуется создавать отдельный ресурс для каждого элемента, можно использовать collect для преобразования коллекции непосредственно внутри метода:
<?php
namespace AppHttpResources;
use IlluminateHttpResourcesJsonResourceCollection;
class SimpleCollection extends ResourceCollection
{
public function toArray($request)
{
return $this->collection->map(function ($item) {
return [
'id' => $item->id,
'title' => $item->title,
'short_description' => substr($item->description, 0, 50),
];
});
}
}
?>
Использование в контроллере:
<?php
namespace AppHttpControllers;
use AppModelsArticle;
use AppHttpResourcesSimpleCollection;
class ArticleController extends Controller
{
public function index()
{
$articles = Article::latest()->take(5)->get();
return new SimpleCollection($articles);
}
}
?>
Результат выполнения кода:
[
{
"id": 1,
"title": "Article 1",
"short_description": "Description of article 1"
},
{
"id": 2,
"title": "Article 2",
"short_description": "Description of article 2"
}
]
Смотрите также
-
класс
JsonResource,
который используется для преобразования отдельных моделей -
метод
toArray,
который определяет структуру данных ресурса -
метод
with,
который добавляет метаданные к ответу -
метод
wrap,
который управляет оберткой данных ресурса