【问题标题】:Yii CActiveDataProvider query caching not working correctlyYii CActiveDataProvider 查询缓存无法正常工作
【发布时间】:2013-08-30 22:05:59
【问题描述】:

我想缓存 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,
        )
    );

但无济于事:查询没有被缓存。

【问题讨论】:

    标签: php caching yii cactivedataprovider


    【解决方案1】:

    CActiveDataProvider 的优点之一是不会立即执行查询。查询仅在您稍后使用 CActiveDataProvider 时执行,例如在 CGridView 中,这将调用 CActiveDataProvider::fetchData 最终触发查询。

    这很有用,因为您可以使用片段缓存,并且您不想在控制器中加载数据只是发现您不需要它,因为片段已缓存。

    这正是这里发生的情况:ActiveRecord ->cache() method 指示 DB Connection 缓存后续查询,但如果查询没有立即执行,则可以在此之前执行其他一些查询,并且此缓存将不起作用。

    我解决了创建个性化 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,
        )
    );

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-24
      相关资源
      最近更新 更多