2012-04-27 168 views
1

我正在尋找一種方式在Yii重新排序CActiveDataProvider。重新排序CActiveDataProvider

當前我正在使用數據提供程序來獲取排序和分頁數據。

然後我通過foreach循環來調整特定字段的數據,現在我需要根據新的調整數據重新對它進行排序。

我無法使用afterFind對模型中的數據進行排序,因爲我需要查詢另一個數據庫(MySQL)來計算出計算值,並且它似乎不喜歡處理過程中的切換。

我不想使用CArrayDataProvider,因爲除非我在調整數據時將控件放入循環中,否則沒有明顯的方式對分頁數據進行分頁,但是我不知道可以返回多少數據,說200條記錄,但唯一調整顯示20似乎違反直覺。

這一切然後推到一個CGridView小部件。

所以現在我需要重新調整下面的陣列升序例如。

$dataProvider = new CActiveDataProvider(blah); 

foreach ($dataProvider->getData() as $data) { 
$data->Score += SomeModel::model()->findByPk(1)->NewScore; 
} 

array(
'Score' => 7 
), 
array(
'Score' => 6 
) 

$this->render('blah', array('data' => $dataProvider); 

回答

2

這聽起來像你應該簡單地實現自己的新CDataProvider一個包裝了現有CDataProvider。您需要重寫幾種方法,但對於其中的大多數方法,您可以簡單地轉發到包裝數據提供程序。該代碼可能最終會看起來像這樣:

$dataProvider = new CActiveDataProvider(...); 
$myProvider = new CustomDataProvider($dataProvider); 

// you could make CustomDataProvider work like this: 
$myProvider->dataMutator = function(&$row, $key) { 
    $row->Score = SomeModel::model()->findByPk(1)->NewScore; 
}; 

$this->render('blah', array('data' => $myProvider); 

CustomDataProvider::fetchData可能是這樣的:

protected function fetchData() 
{ 
    $data = $this->wrappedProvider->fetchData(); 
    array_walk(&$data, $this->dataMutator); 
    uasort($data, function($a, $b) { return $a->Score - $b->Score; }); 
    return $data; 
} 

我已經硬的那種在這裏 - 這個工程的原型,但指定後處理乾淨的排序是不平凡的,因爲:

  • CDataProvider暴露出它忽略sort屬性。完全集成該屬性要麼是非平凡的工作(您必須編寫遵守多個排序條件的代碼等),或者將CustomDataProvider.sort的語義與其基類中的sort進行比較,而將其更改爲語義。 CDataProviderCSort結婚,所以如果你想從OO的角度去尋求最乾淨的解決方案,最好從零開始實施IDataProvider
  • CustomDataProviderCustomDataProvider如果一個'sort property is used, because sort`既不能反映包裝數據提供程序將執行的操作,也不能反映「後處理」排序將同時執行的操作,但是,上述兩者都會影響最終結果。

我建議你得到一個原型工作,然後有一個很好的思考對象模型應該是什麼。

+0

感謝您的這一點,但是我不確定數據在哪一點被採用,或者我應該如何在自定義提供程序中實現它,以便它在Score上排序。 – 2012-04-27 11:17:36

+0

@DamianCrawford:我修改了相當多的答案,看看它現在是否更有用。開頭:現在重寫'fetchData'而不是'getData'。 – Jon 2012-04-27 11:41:30