2012-04-27 115 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