Yii2:ArrayDataProvider 小改动后支持分页查询

前言

实现:通过对ArrayDataProvider的继承和稍微的改动之后,让ArrayDataProvider能够实现指定某一页再查询功能。

Yii2提供了三个数据提供者,分别是:

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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!