Yii2:ArrayDataProvider 小改動後支援分頁查詢

so_easy發表於2020-11-06

前言

實現:透過對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 協議》,轉載必須註明作者和本文連結

相關文章