CActiveDataProvider の利点の 1 つは、クエリがすぐに実行されないことです。クエリは、CActiveDataProvider を後で使用する場合にのみ実行されます。たとえば、CGridView で、CActiveDataProvider::fetchData
最終的にクエリのトリガーを呼び出します。
これは、フラグメント キャッシングを使用できるため便利です。また、フラグメントがキャッシュされているため、コントローラにデータをロードして不要であることが判明することは避けたいと考えています。
これはまさにここで起こっていることです: ActiveRecord->cache()
メソッドは DB 接続に後続のクエリをキャッシュするように指示しますが、クエリがすぐに実行されない場合、このクエリの前に他のクエリが実行される可能性があり、このキャッシュは機能しません。
クエリが実行される直前にモデル キャッシュを設定するパーソナライズされた 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,
)
);