Laravel 5.6: настройка мета-страницы коллекции ресурсов и атрибутов ссылок

Как я могу настроить мета Laravel ResourceCollection и ссылки Информация.

связи должны включать только предыдущий, следующий и сам вместо first, last, prev, next, то есть по умолчанию.

Мета должен включать в себя информацию пагинации как: current_page, total_items, items_per_page, total_pages вместо current_page, from, last_page, path, per_page, to, total.

Вот как мета и информация о ссылках теперь выглядит в ответе JSON:

"meta": {
"currentPage": 2,
"current_page": 1,
"from": 1,
"last_page": 3,
"path": "http://localhost:8000/api",
"per_page": 5,
"to": 5,
"total": 14
},
"links": {
"self": "http://localhost:8000/api",
"first": "http://localhost:8000/api?page=1",
"last": "http://localhost:8000/api?page=3",
"prev": null,
"next": "http://localhost:8000/api?page=2"}

.. Я хочу, чтобы это было что-то вроде:

"meta": {
"current_page": 1,
"total_items": 15,
"per_page": 5,
"total_pages": 3
},
"links": {
"prev": null,
"next": "http://localhost:8000/api?page=2""self": "http://localhost:8000/api",
}

1

Решение

Я не был фанатом того, как в Laravel реализованы нумераторы страниц и ресурсы, так как сложно делать определенные вещи, такие как проблема, которую вы упомянули.

Внутренности

Прежде чем вы сможете настроить свои ответы так, как вы хотите, вам сначала необходимо понять, как ResourceCollections преобразуются в ответы.

Оригинал toResponse Метод для сбора ресурсов выглядит так:

public function toResponse($request)
{
return $this->resource instanceof AbstractPaginator
? (new PaginatedResourceResponse($this))->toResponse($request)
: parent::toResponse($request);
}

Если вы посмотрите дальше в PaginatedResourceResponse класс вы увидите следующий код.

...
protected function paginationLinks($paginated)
{
return [
'first' => $paginated['first_page_url'] ?? null,
'last' => $paginated['last_page_url'] ?? null,
'prev' => $paginated['prev_page_url'] ?? null,
'next' => $paginated['next_page_url'] ?? null,
];
}
...

protected function meta($paginated)
{
return Arr::except($paginated, [
'data',
'first_page_url',
'last_page_url',
'prev_page_url',
'next_page_url',
]);
}

Я рекомендую прочитать Illuminate\Http\Resources\Json\PaginatedResourceResponse а также Illuminate\Http\Resources\Json\ResourceResponse чтобы полностью понять, что происходит.

Решение 1. Создайте пользовательский PaginatedResourceResponse.

Одним из решений является создание нового класса, который расширяет PaginatedResourceResponseи переопределить paginationLinks метод.

Так это выглядит примерно так:

use Illuminate\Http\Resources\Json\PaginatedResourceResponse;

class CustomPaginatedResourceResponse extends PaginatedResourceResponse
{
protected function paginationLinks($paginated)
{
return [
'prev' => $paginated['prev_page_url'] ?? null,
'next' => $paginated['next_page_url'] ?? null,
];
}

protected function meta($paginated)
{
$metaData = parent::meta($paginated);
return [
'current_page' => $metaData['current_page'] ?? null,
'total_items' => $metaData['total'] ?? null,
'per_page' => $metaData['per_page'] ?? null,
'total_pages' => $metaData['total'] ?? null,
];
}
}

Тогда вы можете переопределить ваш toResponse способ выглядеть примерно так:

public function toResponse($request)
{
return $this->resource instanceof AbstractPaginator
? (new CustomPaginatedResourceResponse($this))->toResponse($request)
: parent::toResponse($request);
}

Вы можете рассмотреть возможность переопределения других методов, если хотите дополнительно настроить свой ответ.

Решение 2: переопределить toResponse в ResourceCollection

Вместо переопределения PaginatedResourceResponseВы можете просто переопределить toResponse метод в ResourceCollection с облегченной версией аналогичного кода, например, так:

public function toResponse($request)
{
$data = $this->resolve($request);
if ($data instanceof Collection) {
$data = $data->all();
}

$paginated = $this->resource->toArray();
// perform a dd($paginated) to see how $paginated looks like

$json = array_merge_recursive(
[
self::$wrap => $data
],
[
'links' => [
'first' => $paginated['first_page_url'] ?? null,
'last' => $paginated['last_page_url'] ?? null,
'prev' => $paginated['prev_page_url'] ?? null,
'next' => $paginated['next_page_url'] ?? null,
],
'meta' => [
'current_page' => $metaData['current_page'] ?? null,
'total_items' => $metaData['total'] ?? null,
'per_page' => $metaData['per_page'] ?? null,
'total_pages' => $metaData['total'] ?? null,
],
],
$this->with($request),
$this->additional
);

$status = $this->resource instanceof Model && $this->resource->wasRecentlyCreated ? 201 : 200;

return response()->json($json, $status);
}

Решение 3: переопределить withResponse метод

Более простой, но, возможно, менее мощный вариант — просто переопределить withResponse в коллекции ресурсов вот так:

public function withResponse($request, $response)
{
$data = $response->getData(true);
$prev = $data['links']['prev'];
$next = $data['links']['next'];
$self = $data['links']['self'];
$data['links'] = compact('prev', 'next', 'self');
$response->setData($data);
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]