想接触一下memcached和memcache,就搭了个环境来玩玩,
不过在结合CActiveDataProvider和CMemCache使用的时候,遇到了一些问题,当然是因为我对于缓存,页面缓存,片段缓存的概念不是很清晰造成的,这些在我上一个帖子就体现出来了,
http://www.yiiframework.com/forum/index.php?/topic/14909-使用cmemcache的错误/
真的很烂
感谢Q群:Yii技术互助平台(80196965)里面的 数字,Leric,他们热心解答了我遇到的一些概念上的问题。
OK,回到正题,因为是使用CActiveDataProvider和CMemCache,所以中间还是遇到了不少问题,主要体现在:
我是model里面做缓存的,所以用CActiveDataProvider的时候,就会出现,翻页了,但是页面里面的数据没有发生改变,于是,我进行了一系列的修改:
Model层:
class Product extends CActiveRecord
{
public $cacheKey = 'product'; //这个用途就是用来区分不同的cache的,后面会体会到。
//.......其它代码
//To newbie: 为什么要覆盖这个方法呢?是因为使用CActiveDataProvider的时候,它是调用这个方法来获取数据的。
public function findAll($condition='',$params=array())
{
$cache = Yii::app()->cache;
if ($cache->get($this->cacheKey) === false)
{
$rs = parent::findAll($condition, $params);
$cache->set($this->cacheKey, $rs, 30);
}
else
{
$rs = $cache->get($this->cacheKey);
}
return $rs;
}
}
新建了一个MyActiveDataProvider,继承于CActiveDataProvider,目的是覆盖fetchData()这个方法,赋值给model的cacheKey(见上面定义)
class MyActiveDataProvider extends CActiveDataProvider
{
public $modelCacheKey; //这个属性就是用来赋值给model的cacheKey
protected function fetchData()
{
$criteria=clone $this->getCriteria();
$baseCriteria=$this->model->getDbCriteria(false);
if(($pagination=$this->getPagination())!==false)
{
if($baseCriteria!==null)
$this->model->setDbCriteria(clone $baseCriteria);
$pagination->setItemCount($this->getTotalItemCount());
$pagination->applyLimit($criteria);
}
if(($sort=$this->getSort())!==false)
{
if($baseCriteria!==null)
{
$c=clone $baseCriteria;
$c->mergeWith($criteria);
$this->model->setDbCriteria($c);
}
else
$this->model->setDbCriteria($criteria);
$sort->applyOrder($criteria);
}
//这里赋值到model的cacheKey
if (!empty($this->modelCacheKey))
{
$this->model->cacheKey = $this->modelCacheKey;
}
$this->model->setDbCriteria($baseCriteria);
return $this->model->findAll($criteria);
}
}
Controller层
public function actionIndex()
{
//在这个方法里面,我使用了两次MyActiveDataProvider,都是从Product里面取数据的
$modelCacheKey = empty($_GET['hot']) ? 'site_index_hot_0' : 'site_index_hot_'.$_GET['hot'];
$ads = new MyActiveDataProvider(
'Product',
array(
'criteria'=>array(
'condition'=>'display=1 AND ad=1',
),
)
);
$models = new MyActiveDataProvider(
'Product',
array(
'criteria'=>array(
'condition'=>'display=1 ad<>1',
),
'pagination'=>array(
'pageSize'=>2,
'pageVar'=>'hot',
),
'modelCacheKey'=>$modelCacheKey, //这里是亮点,通过MyActiveDataProvider对model的cacheKey赋值!
)
);
$this->render(
'index',
array(
"models"=>$models,
"ads"=>$ads,
)
);
}
View层
<?php $this->widget('zii.widgets.CListView', array(
'ajaxUpdate'=>false,
'dataProvider'=>$models,
'itemView'=>'_view_models',
'itemsTagName'=>'ul',
'itemsCssClass'=>'lists',
'template'=>"{items}\n{pager}",
'viewData'=>array('modelsCount'=>count($models->getData())),
'pager'=>array(
'class'=>'CLinkPager',
'prevPageLabel'=>'上一页',
'nextPageLabel'=>'下一页',
'header'=>'',
'cssFile'=>$this->themeCss('pager.css'),
)
)); ?>
Maybe FAQ:
- 为什么要在model里面定义一个$cacheKey?
因为在缓存里面,是根据不同的key来保存的,就像是array里面的$key=>$value,而且你会发现,我在Controller层,用了两次MyActiveDataProvider,而且都是调用Product这个model的,如果它们都要缓存的话,那就会冲突了,都会取出同样的数据。还有分页,上面的代码里面,我会根据拿到的分页的数值($_GET[‘hot’])来写/取model里面的值
- 为什么要自己定义一个类来继承CActiveDataProvider?
上面也提到了,是因为要对model的$cacheKey赋值
- 这些代码有什么实际用途吗?
不好意思,还没有实际的应用。
- 关于性能?
同问。。。
无任欢迎拍砖和交流,