
Laravel Resource 的核心目标是将 Eloquent 模型转换为结构化的 JSON 响应。当处理一个模型集合时,我们通常会使用 ResourceCollection。同时,Laravel 的分页功能(如 paginate() 方法)会返回一个 LengthAwarePaginator 实例,该实例不仅包含当前页的数据,还包含了总记录数、当前页码、每页数量以及最重要的——分页链接等元数据。
ResourceCollection 的设计初衷之一就是能够无缝地接收这个 LengthAwarePaginator 实例。当 ResourceCollection 接收到一个分页器时,它会自动解析并将其格式化为标准的 JSON 结构,通常包含以下顶级键:
这种自动化的处理极大地简化了 API 的开发,使得前端可以轻松地解析响应并构建分页 UI。
最常见且推荐的做法是将需要分页的集合作为 API 的顶层响应返回。这意味着你的路由或控制器直接返回一个 ResourceCollection 实例,并传入 paginate() 方法返回的 LengthAwarePaginator。
示例代码:
首先,假设我们有一个 User 模型,并为其创建了 UserResource 和 UserCollection。
UserResource (单个用户资源的转换)
// app/Http/Resources/UserResource.php
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
// ... 其他用户属性
];
}
}UserCollection (用户集合的转换)ResourceCollection 默认会处理分页器的 data、links 和 meta。通常情况下,你不需要在 toArray 方法中显式地添加 links 和 meta,除非你需要自定义它们的结构。data 键会自动填充 UserResource 转换后的数据。
// app/Http/Resources/UserCollection.php
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class UserCollection extends ResourceCollection
{
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
// ResourceCollection 会自动处理 data, links, meta
// 如果需要自定义,可以这样:
return parent::toArray($request); // 调用父类的 toArray 以获取默认的分页结构
// 或者自定义 data 键下的内容,但links和meta通常由父类处理
// return [
// 'data' => $this->collection, // 这里的 $this->collection 已经是被转换过的资源集合
// // 'links' 和 'meta' 会自动添加
// ];
}
}路由或控制器中返回分页数据 在你的路由定义或控制器方法中,直接将 User::paginate() 返回的 LengthAwarePaginator 实例传递给 UserCollection。
// routes/api.php 或 Controller 方法中
use App\Http\Resources\UserCollection;
use App\Models\User;
use Illuminate\Support\Facades\Route;
Route::get('/users', function () {
// 直接将 User::paginate() 返回的 LengthAwarePaginator 实例传递给 UserCollection
return new UserCollection(User::paginate(15));
});当访问 /users 接口时,你将得到一个包含 data、links 和 meta 键的 JSON 响应,其中 links 键下包含了所有必要的分页链接。
AGECMS商业会云管理电子名片是一款专为商务人士设计的全方位互动电子名片软件。它结合了现代商务交流的便捷性与高效性,通过数字化的方式,帮助用户快速分享和推广自己的专业形象。此系统集成了多项功能,包括个人信息展示、多媒体互动、客户管理以及社交网络连接等,是商务沟通和品牌推广的得力工具。 核心功能:个人及企业信息展示:用户可以自定义电子名片中的信息内容,包括姓名、职位、企业Logo、联系信息(电话、
0
{
"data": [
{
"id": 1,
"name": "User 1",
"email": "user1@example.com"
},
// ... 其他用户数据
],
"links": {
"first": "http://localhost/api/users?page=1",
"last": "http://localhost/api/users?page=N",
"prev": null,
"next": "http://localhost/api/users?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": N,
"path": "http://localhost/api/users",
"per_page": 15,
"to": 15,
"total": M
}
}原始问题中提到了在父资源(SectionResource)中嵌套子集合(items)并尝试对其进行分页:
// SectionResource 的 toArray 方法片段 "items" => new ItemCollection($this->items()->paginate(20)),
虽然 new ItemCollection($this->items()->paginate(20)) 会让 ItemCollection 接收到一个 LengthAwarePaginator 实例,但如果 ItemCollection 的 toArray 方法只是简单地 map 集合数据,它将不会在 items 键下自动暴露分页链接和元数据。这是因为 ResourceCollection 默认的 links 和 meta 键是针对其自身作为顶层响应时生效的。
问题分析: 当你在 SectionResource 中返回 new ItemCollection(...) 时,ItemCollection 的 toArray 方法被调用。如果 ItemCollection 的 toArray 方法像你提供的示例那样,仅仅 map 集合:
// ItemCollection 的 toArray 方法片段
public function toArray($request)
{
return $this->collection->map(function ($item) {
// ... 转换逻辑
});
}那么最终在 SectionResource 的响应中,items 键下的值将只是一个纯粹的数组,不包含任何分页信息。
解决方案与建议:
推荐方案:将嵌套资源作为独立的可分页端点暴露。 这是处理嵌套资源分页最推荐和符合 RESTful API 设计原则的方式。如果 items 集合本身需要完整的、可导航的分页功能,那么它应该拥有自己的独立 API 端点。 例如,你可以为 Section 的 items 创建一个这样的路由:
// routes/api.php 或 Controller 方法中
use App\Http\Resources\ItemCollection;
use App\Models\Section;
Route::get('/sections/{section}/items', function (Section $section) {
return new ItemCollection($section->items()->paginate(20));
});这样,当客户端需要 Section 的 items 并进行分页时,它可以直接请求 /api/sections/{section_id}/items,并获得一个包含 data、links 和 meta 的标准分页响应。在 SectionResource 中,items 字段可以只返回一个简略的列表或一个指向这个独立端点的链接。
非典型方案:在嵌套集合中手动暴露分页元数据。 如果你确实需要在父资源内部的嵌套结构中包含子集合的分页链接和元数据,你需要修改 ItemCollection 的 toArray 方法,使其能够识别并暴露其接收到的 LengthAwarePaginator 的信息。 请注意: 这种做法会导致 API 响应的结构变得更深且可能不那么直观,通常不推荐。
// app/Http/Resources/ItemCollection.php
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Pagination\LengthAwarePaginator; // 引入分页器类
class ItemCollection extends ResourceCollection
{
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
// 检查 $this->resource 是否为 LengthAwarePaginator 实例
if ($this->resource instanceof LengthAwarePaginator) {
// 如果是,则手动构建包含 data, links, meta 的结构
return [
'data' => $this->collection->map(function ($item) {
return [
"id" => $item->id ,
"name" => $item->name ,
"slug" => $item->slug ,
"image" => imageGenerate("items" , $item->image) ,
"code" => $item->code ,
"category" => $item->category->name??""
];
}),
'links' => $this->resource->linkCollection(), // 获取分页链接
'meta' => $this->resource->toArray()['meta'], // 获取分页元数据
];
}
// 如果不是分页器,则按原始逻辑返回
return $this->collection->map(function ($item) {
return [
"id" => $item->id ,
"name" => $item->name ,
"slug" => $item->slug ,
"image" => imageGenerate("items" , $item->image) ,
"code" => $item->code ,
"category" => $item->category->name??""
];
});
}
}使用此修改后的 ItemCollection,当它被 SectionResource 调用时,items 键下将包含 data、links 和 meta。然而,这会使得 SectionResource 的响应结构变得复杂:
{
"name": "Section Name",
"slug": "section-slug",
// ... 其他 Section 属性
"items": {
"data": [
{ /* Item 1 */ },
{ /* Item 2 */ }
],
"links": { /* Item Pagination Links */ },
"meta": { /* Item Pagination Meta */ }
}
}这种深层嵌套的结构可能不利于 API 的可读性和维护性。
在 Laravel 中展示分页链接的最佳实践是利用 ResourceCollection 来封装 LengthAwarePaginator 实例,从而在 API 响应的顶层提供规范的 data、links 和 meta 结构。对于嵌套集合的分页需求,强烈建议为其创建独立的 API 端点,以保持 API 结构的扁平化和一致性。尽管可以通过修改 ResourceCollection 来在嵌套结构中暴露分页信息,但这通常会导致响应复杂化,应谨慎使用。优先采用顶层分页策略,将有助于构建更清晰、更易于消费的 API。
以上就是Laravel Resource 中集合分页链接的展示与处理的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号