在 Laravel 中,无法替换分页响应的默认结构。这是我想要实现的结构:
return response()->json([
'data' => $items->items()
'meta' => [
'current_page' => $items->currentPage(),
'from' => $items->firstItem(),
'last_page' => $items->lastPage(),
'per_page' => $items->perPage(),
'to' => $items->lastItem(),
'total' => $items->total(),
];
]);
我之前已经通过资源收集解决了这个问题。 Laravel 不支持开箱即用,因此需要做一些工作。
首先,您必须重写
App\Http\Resources\PaginatedResourceResponse
类,这是呈现分页响应的默认方式。然后您可以覆盖返回的分页数据的默认结构。
class CustomPaginatedResourceResponse extends PaginatedResourceResponse
{
}
然后请创建一个使用自定义分页资源的资源集合。
class ItemsResource extends ResourceCollection
{
public function toArray($request)
{
}
// Override the toResponse method.
public function toResponse($request)
{
return $this->resource instanceof AbstractPaginator
? (new CustomPaginatedResourceResponse($this))->toResponse($request)
: parent::toResponse($request);
}
}
最后,您只需使用控制器中的
ItemsResource
即可。
return new ItemsResource($items);
这需要了解api资源和源码。请花一些时间阅读 docs 并弄清楚
App\Http\Resources\PaginatedResourceResponse
是如何使用的。
在 Laravel 10 中(不确定从哪个版本开始),您可以在
paginationInformation
(Laravel 文档)上实现方法
ResourceCollection
,您可以在其中调整分页数据的默认格式。我这样上课:
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
class PaginatedJsonResourceCollection extends AnonymousResourceCollection
{
/**
* Adjust pagination data format
*
* @param Request $request
* @param array $paginated
* @param array $default
* @return array
*/
public function paginationInformation(Request $request, array $paginated, array $default)
{
unset($default['links']);
$default['meta'] = [
'page' => $default['meta']['current_page'],
'lastPage' => $default['meta']['last_page'],
'perPage' => $default['meta']['per_page'],
'total' => $default['meta']['total']
];
return $default;
}
}
如您所见,我从响应中完全删除了
links
属性,并根据我的需要调整了 meta
字段。
然后我需要告诉 Laravel 在创建集合时使用这个自定义类,所以我创建了
PaginatedJsonResource
类:
use Illuminate\Http\Resources\Json\JsonResource;
class PaginatedJsonResource extends JsonResource
{
/**
* Create a new resource collection instance.
*
* @param mixed $resource
* @return PaginatedJsonResourceCollection
*/
protected static function newCollection($resource): PaginatedJsonResourceCollection
{
return new PaginatedJsonResourceCollection($resource, static::class);
}
}
然后让我所有的资源扩展这个类:
class ArticleResource extends PaginatedJsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->content,
];
}
}
现在每当我返回控制器时
return ArticleResource::collection(Article::paginate());
我以自定义格式获取分页数据:
{
"data": [
{
"id": 12345,
"title": "Article 1",
"content": "..."
},
{
"id": 12346,
"title": "Article 2",
"content": "..."
},
...
],
"meta": {
"page": 1,
"lastPage": 50,
"perPage": 15,
"total": 1000
}
}
我尝试将
paginationInformation()
直接实现到我的 Resource
中,但它永远不会调用 paginationInformation()
,有什么想法吗?
class SomeResource extends JsonResource
{
public function toArray(Request $request): array
{
//
}
public function paginationInformation($request, $paginated, $default)
{
dd("called");
}
}
通过使用调用:
public function index(Request $request, OrderFilter $filters)
{
return OrderResource::collection(Order::where('x', 'y')->paginate());
}