Yii Framework Forum: Cgridview With Custom Dataprovider That Doesn't Load All Records From Source (Lazy Loading) - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Cgridview With Custom Dataprovider That Doesn't Load All Records From Source (Lazy Loading) Rate Topic: -----

#1 User is offline   Twisted Whisper 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 9
  • Joined: 21-June 13

Posted 30 June 2013 - 09:54 AM

I'm a 5-day Yii fan trying to learn the ropes of this great framework. I would really appreciate it if you could bear with me reading through my problem and help me out.

So here goes, I'm retrieving a list of products sold by a particular merchant of an online marketplace through its web service. When I query the web service like this
api.marketplace.com?merchant_id=1234


I'll get back the response in JSON which consists of two main pieces of data
1. The number of products sold by Merchant 1234 (total_products)
2. The list (array) of the products sold (list_product). Each element in this array represents one distinct Product object with two fields: product_id and product_name respectively.

So if total_products = 934, there'll be 934 elements in the array.
When I put it in codes, my derived DataProvider looks like this
class ProductDataProvider extends CDataProvider /* or should I extend other better class? */ {
    public function __construct($config = array()) {
	foreach($config as $key=>$value)
	    $this->$key=$value;
    }    

    protected function fetchData() {
        $request = "api.marketplace.com?merchant_id=1234";
        $response = retrieveProductsAndProcessJSONResponseIntoAppropriateDataStructure($request);
        $this->setTotalItemCount($response->total_products);

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

        return $response->list_products;
    }

    protected function calculateTotalItemCount() {
        return $this->getTotalItemCount();
    }
}


My model
class Product extends CModel {
    public $product_id;
    public $product_name;

    public function display() {
        return new ProductDataProvider(array(
            'pagination'=>array(
		'pageSize'=>10,
        ));
    }
}


and my View
$this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'product-grid',
    'dataProvider'=>$model->display(),
    'columns'=>array(
        'product_id',
        'product_name',
    ),
));


This works well with pagination and all that. However retrieving all 934 products is taking a bit too long. We can do this to the web service.
api.marketplace.com?merchant_id=1234&page_size=10&page_no=1


This will only retrieve the first 10 records. We can play around with the query string variable page_no to retrieve subsequent pages of products in groups of 10. The total_products returned from the web service will still be 934.

So my question is, how do I put this into play so that the ProductDataProvider only retrieves 10 product at any one time and load it into CGridView? The CGridView will have to know that there are a total of 934 products to enable pagination. User browsing to other pages of the CGridView will trigger the ProductDataProvider to retrieve the next 10 records corresponding to the page number being viewed. I hope that my long winded question is comprehensible.
0

#2 User is offline   softark 

  • Keep It Simple
  • Yii
  • Group: Moderators
  • Posts: 2,085
  • Joined: 16-February 11
  • Location:Japan

Posted 30 June 2013 - 07:50 PM

Hi Twisted Whisper, welcome to the forum.

This is from the source code of CArrayDataProvider:

Quote

protected function fetchData()
{
	...
	if(($pagination=$this->getPagination())!==false)
	{
		$pagination->setItemCount($this->getTotalItemCount());
		return array_slice($this->rawData, $pagination->getOffset(), $pagination->getLimit());
	}
	...


So, isn't it really easy to implement pagination in your data provider too?
0

#3 User is offline   Twisted Whisper 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 9
  • Joined: 21-June 13

Posted 30 June 2013 - 10:56 PM

View Postsoftark, on 30 June 2013 - 07:50 PM, said:

Hi Twisted Whisper, welcome to the forum.

This is from the source code of CArrayDataProvider:

So, isn't it really easy to implement pagination in your data provider too?


Hi softark, thanks for taking the time reading and replying.

But this means that I'll have to load all 934 records into $this->rawData. My requirement is only to load a page of data from the web service (10 records). Do I create an array of 934 empty elements, and only populate 10 of them in the appropriate order in the array and then assign that array to $this->rawData to give the illusion to CGridView that there are indeed 934 elements (most of them empty but it doesn't matter since the CGridView is only displaying 10 visible records while the empty ones are "invisible" hidden in other pages)
0

#4 User is offline   Twisted Whisper 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 9
  • Joined: 21-June 13

Posted 30 June 2013 - 11:02 PM

Scratch my #3 post. I think I get what you mean. I'll try it out first and will update you on the outcome.
0

#5 User is offline   softark 

  • Keep It Simple
  • Yii
  • Group: Moderators
  • Posts: 2,085
  • Joined: 16-February 11
  • Location:Japan

Posted 30 June 2013 - 11:23 PM

Yeah, I'm sure you got it.

I hope $pagination->getOffset() and $pagination->getLimit() will provide the necessary api parameters.
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users