Laravel 的限制条数再分页
本文搬运自我自己的博客
1. 需求
有这么一个需求,我想取出一个表(比如user
表)中,按照某一排序规则(比如按照时间倒叙),取出前100
条,进行分页,每页10
条。应该如何实现?自然而然可能会这样写下:
$users = User::orderBy('id','desc')->limit(100)->paginate(10)
最后打印结果可以发现,limit
并未生效,依旧是将所有结果进行分页。
2. 准备
本文中用到的user
模型,数据,控制器,路由之类的都已经在另一篇文章 手摸手教你让Laravel开发Api更得心应手 创建好了。
users
表中的数据
3. 限制条数再分页
继续通过paginate
方法来分页以及行不通了。确幸Laravel
框架给我们提供了自定义分页类,我们通过使用自定义分页类来达到我们限制条数再分页的需求。
下面我们分别讲解数组手动分页
以及模型对象手动分页
3.1. 需求
通过id
来倒叙排序,并且取出前6条来分页,每页2条数据
3.2. 数组
3.2.1. 代码
public function index1(Request $request){
//将对象结果集转为数组结果集
$data = User::orderBy('id','desc')->limit(6)->get()->toArray();
//传入页数,默认值为1
$page = $request->page ?? 1;
//每页的条数
$perPage = 2;
//计算每页分页的初始位置
$offset = ($page * $perPage) - $perPage;
//实例化LengthAwarePaginator类,并传入对应的参数
$data = new LengthAwarePaginator(array_slice($data, $offset, $perPage, true), count($data), $perPage,$page, ['path' => $request->url(), 'query' => $request->query()]);
return $data;
}
3.2.2. 测试
符合我们的需求
3.2.3. 适用
比较适用于自建的数组想进行分页。
因为一开始就被转换为数组了,所以想要用模型中的方法是不可能了。
3.2.4. 缺点
1.无法使用对应模型里的方法。
2.内置的Api资源无法正常使用。
当我们的UserResource.php
里的内容为这样时:
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id'=>$this->id,
'name' => $this->name,
'status' => UserEnum::getStatusName($this->status),
'created_at'=>(string)$this->created_at,
'updated_at'=>(string)$this->updated_at
];
}
}
此时在控制器中使用Api资源来返回结果
return UserResource::collection($data);
报错,提示Trying to get property 'id' of non-object
。这是由于我们传入到内置分页类中的是数组而不是一开始的对象形式,所以提示找不到这个属性。我们只需要进行一些稍微的修改。
public function toArray($request)
{
return [
'id'=>$this->resource['id'],
'name' => $this->resource['name'],
'status' => UserEnum::getStatusName($this->resource['status']),
'created_at'=>(string)$this->resource['created_at'],
'updated_at'=>(string)$this->resource['updated_at']
];
}
此时返回结果正常,但是不会报错。但是还是有很多问题,比如,无法使用数据包裹
,条件关联
等等。因为传入的分页是数组而不是对象导致的。
所以说,数组来进行分页,只适用于自己构建的数据数组。
3.3. 对象
接着解决上面的痛点,一开始我们就将对象结果集转为了数组结果集(百度上千篇一律都是转成了数组结果集),所以让导致模型方法以及Api资源都不能很好地使用。
现在我们不转换为数组,直接用对象结果集来进行自定义分页。
先来看一个函数
array_slice()
这是上面数组能进行分页的关键,可以指定从第几个元素开始,显示几个元素。
那对象结果集是否有类似的方法可以调用?这样我们就可以做出对象结果集的分页了。答案是有的。文档中的集合方法slice()
拥有一样的功能。
3.3.1. 代码
public function index(Request $request){
$data = User::orderBy('id','desc')->limit(6)->get();
//传入页数,默认值为1
$page = $request->page ?? 1;
//每页的条数
$perPage = 2;
//计算每页分页的初始位置
$offset = ($page * $perPage) - $perPage;
//实例化LengthAwarePaginator类,并传入对应的参数
$data = new LengthAwarePaginator($data->slice($offset,$perPage), count($data), $perPage,$page, ['path' => $request->url(), 'query' => $request->query()]);
return UserResource::collection($data);
}
此时UserResource.php
文件中的内容为
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id'=>$this->id,
'name' => $this->name,
'status' => UserEnum::getStatusName($this->status),
'created_at'=>(string)$this->created_at,
'updated_at'=>(string)$this->updated_at
];
}
}
3.3.2. 测试
没有任何错误,符合我们的要求
3.3.3. 适用
非自建数组,想使用模型的方法或者使用Api资源。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: