Pagination With Cgridview And Carraydataprovider

I’m attempting to use a GridView to display and paginate records retrieved from an API. The API returns thousands (and thousands) of records, but thankfully provides a way to limit the returned data to a subset. I can specify the number of records I want back, and the number with which to start. The API is nice enough to tell me how many total records there are for things like pagination.

Since the API returns the records as an array, I’m using the ArrayDataProvider. Assuming the API response is $this->applications, my data provider looks like this:




    $dataProvider = new CArrayDataProvider($this->applications->List, array(

        'id' => 'applications',

        'keyField' => 'ApplicationId',

        'pagination' => array(

            'pageSize' => 20,

            'pageVar' => 'page'

        ),

        'totalItemCount' => $this->applications->Total

    ));



When I allow the API to return all the records, GridView displays and paginates properly:




    $this->widget(

        'zii.widgets.grid.CGridView', array(

            'ajaxUpdate' => false,

            'columns' => array(

                [...]

            ),

            'dataProvider' => $dataProvider,

        )

    );



My problem comes when I want to paginate over the entire result set, but have the API only return a subset of data. So for example, If I limit the returned records to 20, despite the totalItemCount being in the thousands, no pagination controls will be displayed.

If I return more than 20 records (say 21-1000), the proper pagination controls to navigate over the 1000 records will be displayed properly, but pagination itself does not work correctly. If 21-40 is page 2, and records 21-1000 are returned by the API, page 2 will actually represent 41-60. Click page 3 (API results 61-80), I’ll actually get 101-120.

So my question is this: Can I accomplish what I’m attempting using GridView and ArrayDataProvider? I’m quite certain I’m going about it in the wrong way, but I’m also pretty confident there’s a way to do this. It seems silly to me that the GridView would require all records to be loaded in order to paginate.

Any advice from the Yii citizens out there?

Thanks for your help.

Still silly, but apparently so when using ArrayDataProvider. The solution requires extending CArrayDataProvider class like so:




class ArrayDataProvider extends CArrayDataProvider

{

    protected function fetchData()

    {

        if(($sort = $this->getSort()) !== false && ($order = $sort->getOrderBy()) != '')

            $this->sortData($this->getSortDirections($order));


        if(($pagination = $this->getPagination()) !== false)

            $pagination->setItemCount($this->getTotalItemCount());


        return $this->rawData;

    }

}



Give credit where credit is due: I’m unfortunately unable to embed links, but I found my solution from Georgi Budinov’s post titled “The CArrayDataProvider problem of Yii” from 9 Sept 2011.

Hi De Soto,

Welcome to the forum. :)

Is this blog post what you mean?

http://georgi.budinov.com/2011/09/the-carraydataprovider-problem-of-yii/

It’s interesting.

Are you handling the sorting and paginating outside of CArrayDataProvider all by yourself?

I mean, are you giving the CArrayDataProvider a rawData that has been already sorted and paginated by yourself (or the API that you are using) ?

That’s the one!

Correct. The API takes responsibility for all things typically associated with paginating and sorting data.

Superb .its very usefull.