2013-06-30 74 views
0

我是一個5天的Yii粉絲試圖學習這個偉大的框架的繩索。如果你能忍受我讀完我的問題並幫助我,我會非常感激。CGridview自定義數據提供不加載所有記錄來源(懶加載)

因此,在這裏,我正在檢索由在線市場的特定商家通過其Web服務銷售的產品的列表。當我這樣的查詢

api.marketplace.com?merchant_id=1234 

網絡服務,我會回來它由數據

  1. 由商戶1234出售的產品數量的兩個主要部分(total_products在JSON響應)
  2. 銷售產品的清單(排列)(list_product)。此數組中的每個元素分別代表一個具有兩個字段的不同Product對象:分別爲product_idproduct_name

所以如果total_products = 934,就會有在陣列中934層的元件。 當我把它放在代碼,我得出的DataProvider看起來像這樣

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(); 
    } 
} 

我的模型

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

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

和我查看

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

這與分頁和所有運作良好。但是,檢索所有934產品需要的時間太長。我們可以對Web服務執行此操作。

api.marketplace.com?merchant_id=1234&page_size=10&page_no=1 

這隻會檢索前10條記錄。我們可以玩的查詢字符串變量page_no檢索中的10 total_products從網絡返回組產品後續頁面的服務仍然是934

所以我的問題是,我怎麼放這一點,以便ProductDataProvider只能在任何時候檢索10個產品並將其加載到CGridView中? CGridView必須知道總共有934種產品可以實現分頁。用戶瀏覽到CGridView的其他頁面將觸發ProductDataProvider檢索與正在查看的頁碼相對應的下10條記錄。我希望我的冗長的問題是可以理解的。

+0

研究數據提供者的分頁系統。它通常針對SQL分頁,但是通過自定義分頁類,您應該能夠按需要處理事情。 – acorncom

回答

0

我有同樣的問題。所以,我認爲:

首先,你應該實現從CDataProvider所有3個抽象方法。在你的班級fetchKeys()沒有實施。

其次,分頁邏輯應放在fetchData。例如:

protected function fetchData() { 
    $request = "api.marketplace.com?merchant_id=1234"; 
    // page size 
    $request .= "&page_size=".$this->pagination->pageSize; 
    // current page 
    $request .= "&page_no=".$this->pagination->currentPage; 
    $response = retrieveProductsAndProcessJSONResponseIntoAppropriateDataStructure($request); 

    return $response->list_products; 
} 

若要使用新的自定義數據提供寫水木清華這樣的:

$dataProvider = new CustomDataProvider(); 
$pages = new CPagination($dataProvider->getTotalItemCount()); 
$pages->pageSize = 40; // page size 
$dataProvider->pagination = $pages; 

數據提供商獲得使用calculateTotalItemCount()項目的總數。所以,另外,你應該寫一些邏輯來提供總計數。猜測,您應該在您的API中利用另一種方法來達到此目的。請記住,如果您使用分頁,您的數據提供者將執行2個api請求:第一個用於總項目計數,第二個用於當前頁面項目。有些人可以說只有一個請求就足夠了,但在這種情況下,該請求將返回所有數據(934個元素)。太重了。

這就是你所需要的。

+0

我在一段時間之前看到了它的工作情況,我的方法基本上是相同的,除了代替'$ this-> pagination-> pageSize',我使用了'$ this-> getPagination() - > getLimit()'而不是'$ this-> pagination-> currentPage ',我用'$ this-> getPagination() - > getOffset()'。 無論如何,這是同樣的事情。 Yii提供了不止一種方法來給貓皮。 –

0

我認爲你需要創建自己的自定義數據提供者。請參閱CDataProvider的類參考

Yii中有三個實現的數據提供者。 CActiveDataProvider,CArrayDataProvider和CSqlDataProvider。您可以將它們用作自定義數據提供程序的模型。

+0

我做到了。如果你閱讀我的代碼,我已經創建了我的自定義DataProvider'ProductDataProvider'。但是,這隻會從Web服務中獲取一切。我需要知道如何在不檢索所有記錄的情況下實現延遲加載,但仍然能夠讓CGridView瀏覽其他「未加載」的記錄,這些記錄將在運行中檢索到 –