我想缓存CActiveDataProvider实例的数据库结果。
我在控制器的操作中准备数据提供程序,然后我在CGridView中使用数据提供程序,稍后在某些视图中。
我以前有这段代码:
$cars=new CActiveDataProvider(
'Car'
,
array(
'criteria'=>array(
'condition'=>'brand_id=:brand_id',
'params' => array(':brand_id'=>$model->id),
'order' => 'price',
),
'pagination'=>false,
)
);
并且,在tutorial in the yii wiki之后,我将其更改为:
$cars=new CActiveDataProvider(
Car::model()->cache(3600)
,
array(
'criteria'=>array(
'condition'=>'brand_id=:brand_id',
'params' => array(':brand_id'=>$model->id),
'order' => 'price',
),
'pagination'=>false,
)
);
但无济于事:查询未被缓存。
答案 0 :(得分:2)
CActiveDataProvider的一个优点是不会立即执行查询。只有在稍后使用CActiveDataProvider(例如在CGridView中)时才会执行查询,该调用将调用CActiveDataProvider::fetchData
最终触发查询。
这很有用,因为您可以使用片段缓存,并且您不希望仅在控制器中加载数据以发现您不需要它,因为片段已缓存。
这正是这里发生的事情:ActiveRecord ->cache()
method指示数据库连接缓存后续查询,但如果查询没有立即执行,则可以在此之前执行其他一些查询,并且此缓存不会工作
我解决了创建个性化ActiveDataProvider的问题,该问题将在查询发生之前设置模型缓存:
class CachedActiveDataProvider extends CActiveDataProvider
{
public $cache_duration = null;
public $cache_dependency = null;
/**
* The cache mechanism works by telling the DB Component to cache the next query.
* When fetchData() is called, the DB will cache the next query.
* There is a possibility that fetchData call calculateTotalItemCount()
* and in that function, if this bit is active, we will tell the DB to cache
* 2 queries, the count, and the actual fetch that will come next.
* (if we don't do this, the DB will cache the count query, and will forget about
* the instruction to cache the fetch query)
*
* @var boolean
*/
private $fetching_data = false;
protected function fetchData()
{
if (!is_null($this->cache_duration ))
{
$this->model->cache($this->cache_duration, $this->cache_dependency);
}
$this->fetching_data = true;
$ret = parent::fetchData();
$this->fetching_data = false;
return $ret;
}
protected function calculateTotalItemCount()
{
if (!is_null($this->cache_duration ))
{
$this->model->cache(
$this->cache_duration,
$this->cache_dependency,
$this->fetching_data ? 2 : 1 //if fetching data, cache 2 queries: this count and the sequent fetching
);
}
return parent::calculateTotalItemCount();
}
}
我现在可以使用
来调用它$cars=new CachedActiveDataProvider(
'Car'
,
array(
'criteria'=>array(
'condition'=>'brand_id=:brand_id',
'params' => array(':brand_id'=>$model->id),
'order' => 'price',
),
'pagination'=>false,
'cache_duration' => 3600,
)
);