I want to cache the DB results for a CActiveDataProvider instance.
I prepare the data provider in a controller's action, and then I use the data provider in a CGridView, later in some view.
I used to have this code:
$cars=new CActiveDataProvider(
'Car'
,
array(
'criteria'=>array(
'condition'=>'brand_id=:brand_id',
'params' => array(':brand_id'=>$model->id),
'order' => 'price',
),
'pagination'=>false,
)
);
and, following the tutorial in the yii wiki, I changed it to:
$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,
)
);
but to no avail: the query is not being cached.
One of the advantages of CActiveDataProvider is that the query is NOT performed right away. The query is performed only when you use the CActiveDataProvider later on, say in a CGridView, that will call
CActiveDataProvider::fetchData
eventually triggering the query.This is useful because you can use fragment caching, and you don't want to load data in the controller only to find out that you don't need it, because the fragment is cached.
This is exactly what happens here: the ActiveRecord
->cache()
method instructs the DB Connection to cache the sequent query, but if the query is not immediately executed, some other query could be performed before this one, and this caching will not work.I solved the problem creating a personalized ActiveDataProvider that will set the model cache just before the query taking place:
I can now call it using