Yii2:ArrayDataProvider 小改动后支持分页查询
前言#
实现:通过对 ArrayDataProvider
的继承和稍微的改动之后,让 ArrayDataProvider
能够实现指定某一页再查询功能。
Yii2 提供了三个数据提供者,分别是:
- yii\data\ActiveDataProvider
- yii\data\SqlDataProvider
- yii\data\ArrayDataProvider
对 ArrayDataProvider
的介绍如下:
yii\data\ArrayDataProvider 非常适用于大的数组。数据提供者允许你返回一个 经过一个或者多个字段排序的数组数据页面。为了使用 yii\data\ArrayDataProvider, 你应该指定 allModels 属性作为一个大的数组。 这个大数组的元素既可以是一些关联数组(例如:DAO 查询出来的结果) 也可以是一些对象(例如:Active Record 实例)
在实践过程中,我对 ArrayDataProvider
的理解是:
假设传入一个数组拥有 100 项,每页显示 10 条数据。那么 ArrayDataProvider
就会自动给你分成 10 页。倘若我这个数组很大的话,那么这个数据提供者的效率就会降低。
可是我想让 ArrayDataProvider
拥有如 ActiveDataProvider
的功能:点击哪一页就开始查询哪一页的数据,而不是一开始就将所有数据加载进来。
开始#
我的需求#
我目前正在做 ES 查询的结果用 ArrayDataProvider
提供分页。可是我 ES 返回的数据集合可能很大,几千甚至几万条(当然夸张了)。这么大的数据集合一次性返回给 ArrayDataProvider
做分页肯定不行。于是有没有其他的方案呢,能够让我指定某一页查询。
改造#
本身 ES 是支持分页的,两种方式:
- from
- lastid
对 ES 来说几千几万条数据分页也是最好采用 lastId 的方式,而不是用 from。但是为了能够实现分页功能,用的是 from。lastId 似乎不能跳页(若错求指正)。
于是我只要能够让 ArrayDataProvider
每次只显示 ES 查询的当前页即可实现。于是改动如下:
1、定义一个类 MyArrayDataProvider
继承 ArrayDataProvider
<?php
namespace app\utils;
use yii\data\ArrayDataProvider;
class MyArrayDataProvider extends ArrayDataProvider
{
protected function prepareModels()
{
if (($models = $this->allModels) === null) {
return [];
}
if (($sort = $this->getSort()) !== false) {
$models = $this->sortModels($models, $sort);
}
if (($pagination = $this->getPagination()) !== false) {
$pagination->totalCount = $this->getTotalCount();
if ($pagination->getPageSize() > 0) {
// $models = array_slice($models, $pagination->getOffset(), $pagination->getLimit(), true);
$models = array_slice($models, 0, $pagination->getLimit(), true);
}
}
return $models;
}
}
然后在数据提供者 ArrayDataProvider
改成 MyArrayDataProvider
。用法全部都和文档一样。
<?php
//...
$from = ($page-1) * $pageSize;
// 然后通过ES查询的时候传递 from 分页查询
$dataProvider = new MyArrayDataProvider([
'allModels' => $data, //$data是一个分页查询后的数组
'pagination' => ['pageSize'=>10,], // pagination 用于分页
'totalCount' => $totalCount,
]);
讨论#
毕竟对 Yii 还没有很深入的去学习,你们是怎么做的呢?
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: