Как создать виджет в yii?
Ответ
Виджет чаще всего используется в виде (view). Потому простой(!) пример для этого случая - виджет выводит заголовок и список ссылок (и заголовок, и массив ссылок передаются в момент вызова виджета в виде). Отправляемся в папку extensions и создаем в ней папку testwidgets. В ней создадим файл TestWidget.php и папку views, в которой создадим файл test.php. Как вы могли догадаться, это файл для класса виджета и файл для представления (вида) виджета соответственно.
Код файла TestWidget.php:
1 2 3 4 5 6 7 8 9 |
class TestWidget extends CWidget { public $title=''; public $links=array(); public function run() { $this->render('test',array('title'=>$this->title, 'links'=>$this->links)); } } |
Как видите, название класса совпадает с названием файла и в методе run() данные отправляются в вид test. Php-код views/test.php выглядит следующим образом:
1 2 3 4 5 |
<?php echo $title; foreach ($links as $link) { echo $link.'<br>'; } ?> |
Теперь применим виджет в каком-нибудь виде:
1 2 3 4 5 6 |
<?php $this->widget('ext.testwidgets.TestWidget',array( 'title'=>'Полезные сайты', 'links'=>array('http://www.livelib.ru/quotes', 'https://www.goodreads.com/quotes')) )); ?> |
Заметим, что здесь используется alias ext. Можно по-старому писать так: application.extensions.testwidgets.TestWidget.
Очень важная фраза: $this в представлении указывает на экземпляр виджета, а не на экземпляр контроллера.
В примере выше не использован метод init(). Поэтому приведем более сложный пример, найденный на просторах интернета (спасибо bupy7). Внимание: речь идет о некоторых принципиальных моментах, нет нужды изучать код досконально в данной статье.
Суть в том, что есть скрипт http://flipclockjs.com/ - счетчик времени и необходимо сделать обертку для yii. Файлы скрипта находятся в папке assets (flipclock.css, flipclock.min.js). Рядом с папкой - файлы Flipclock.php и FlipclockWidget.php. И это все, естественно, в папке extensions/flipclock.
А теперь содержимое php-файлов:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php class Flipclock extends CComponent { public static function register() { $assetsUrl = Yii::app()->getAssetManager()->publish( Yii::getPathOfAlias('ext.flipclock.assets') ); Yii::app()->clientScript->registerCssFile($assetsUrl.'/flipclock.css') ->registerScriptFile($assetsUrl.'/flipclock.min.js'); } } |
и файла FlipclockWidget.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?php Yii::import('ext.flipclock.Flipclock'); class FlipclockWidget extends CWidget { public $options = array(); public $selector; public $time; public $varName; public function init() { Flipclock::register(); if ($this->selector === null) { $this->selector = '#' . $this->id; } if ($this->varName === null) { $this->varName = $this->id; } Yii::app()->clientScript->registerScript('flip-clock-' . $this->id, "var {$this->varName} = new FlipClock($(" . CJavaScript::encode($this->selector) . "), ".CJavaScript::encode($this->time).", ".CJavaScript::encode($this->options).");", CClientScript::POS_END ); } public function run() { echo CHtml::tag('div', array('id' => substr($this->selector, 1, strlen($this->selector)))); echo CHtml::closeTag('div'); } |
Собственно применение виджета в каком-нибудь виде:
1 2 3 4 5 6 7 8 |
$this->widget('ext.flipclock.FlipClockWidget', array( 'selector' => '#clock', // ID for the future DIV 'time' => 60, // Seconds 'varName' => 'clock', // Name of variable for control FlipClock 'options' => array( // options of FlipClock ), )); |
Кстати, здесь используется registerScript с параметром CClientScript::POS_END - про это стоит срочно почитать. Что касается виджета, то обратим внимание на метод init(), в котором вызывается статический метод Flipclock::register() (для этого пришлось добавить строку Yii::import('ext.flipclock.Flipclock'); ). Надеюсь, суть понятна. Осталось самостоятельно написать обертку к какому-нибудь простому js-скрипту.