Довольно часто возникает необходимость кешировать результат работы виджета, но материала по этой теме мало. Постепенно пришел к такому решению проблемы: создаем класс Widget и наследуем все свои виджеты от него.
class Widget extends CWidget
{
protected $cacheTime = 3600;
protected $cacheId = null;
public function init()
{
if(!$this->cached())
$this->generate();
}
public function generate()
{
//$this->render(...);
}
public function cached()
{
if($this->cacheId === null)
$this->cacheId = 'WidgetCache_' . get_class($this);
$content = Yii::app()->cache->get($this->cacheId);
if($content === false)
return false;
echo $content;
return true;
}
public function render($view, $data = null)
{
$content = parent::render($view, $data, true);
Yii::app()->cache->set($this->cacheId, $content, $this->cacheTime);
echo $content;
}
}
class WSample extends Widget
{
public function generate()
{
$this->render('sample');
}
}
class WSample2 extends Widget
{
public $param = 2;
public function init() //У виджета есть параметр, по-этому будет несколько кешей
{
$this->cacheId = 'WSample2_' . $this->param;
$this->cacheTime = 60;
if(!$this->cached())
$this->render('sample', $this->param);
}
}
Я знаю, что есть 2 недостатка:
-
В методе Widget.generate() для отображения нужно использовать только Widget.render()
-
Класс только для виджетов, которым не нужен endWidget
Оба недостатка не очень важные, т.к. в моей практики очень редко встречаются. Хотелось бы услышать критику или взглянуть на ваше решение этой проблемы.
P.S. Конечно, самое простое решение, это:
<?php if($this->beginCache($id)){
$this->widget('...');
$this->endCache(); } ?>
но мне оно не очень нравится, т.к. при большом количестве виджетов возникает каша, да и править в нескольких местах нестандартное время кеша тоже неудобно.