[英]Laravel 5.6: Customise a paginated resource collection meta and links attributes
如何自定義 Laravel ResourceCollection 元和鏈接信息。
鏈接應該只包含prev,next 和 self而不是默認的 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",
}
我不喜歡 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
以了解發生了什么。
一種解決方案是創建一個擴展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);
}
如果您想進一步自定義您的響應,您可以考慮覆蓋覆蓋其他方法。
toResponse
中的toResponse
相反重寫的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);
}
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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.