Поскольку создание расширений подразумевает их использование сторонними разработчиками, процесс создания требует дополнительных усилий. Ниже приведены основные правила, которые необходимо соблюдать при создании расширений:
Ниже мы расскажем о том, как создать новое расширение в соответствии с классификацией, приведенной в обзоре. Пояснения в равной степени распространяются и на расширения, используемые исключительно в собственных проектах.
Компонент приложения должен реализовывать интерфейс IApplicationComponent или расширять класс CApplicationComponent. Основной метод, который необходимо реализовать, - IApplicationComponent::init. В этом методе компонент инициализируется. Метод вызывается после того, как компонент создан и получены начальные значения, обозначенные в конфигурации приложения.
По умолчанию, компонент приложения создается и инициализируется только в момент первого обращения к нему в ходе обработки запроса. Если необходимо принудительно создавать компонент сразу после создания экземпляра приложения, то нужно добавить этого идентификатор компонента в свойство CApplication::preload.
Для того, чтобы создать поведение необходимо реализовать интерфейс IBehavior. Для удобства в Yii имеется класс CBehavior, реализующий этот интерфейс и предоставляющий некоторые общие методы. Наследуемые классы могут реализовать дополнительные методы, которые будут доступны в компонентах, к которым прикреплено поведение.
При разработке поведений для CModel и CActiveRecord можно наследовать CModelBehavior и, соответственно, CActiveRecordBehavior. Эти базовые классы предоставляют дополнительные возможности, специально созданные для CModel и CActiveRecord. К примеру, класс CActiveRecordBehavior реализует набор методов для обработки событий жизненного цикла ActiveRecord. Наследуемый класс, таким образом, может перекрыть эти методы и выполнить код, участвующий в жизненном цикле AR.
Следующий код демонстрирует пример поведения ActiveRecord. Если это поведение
назначено объекту AR и вызван метод save()
, атрибутам create_time
и
update_time
будет автоматически выставлено текущее время.
class TimestampBehavior extends CActiveRecordBehavior
{
public function beforeSave($event)
{
if($this->owner->isNewRecord)
$this->owner->create_time=time();
else
$this->owner->update_time=time();
}
}
Виджет должен расширять класс CWidget или производные от него.
Наиболее простой способ создать виджет - расширить существующий виджет и переопределить его методы или заменить значения по умолчанию. Например, если вы хотите заменить CSS-стиль для CTabView, то, используя виджет, нужно сконфигурировать свойство CTabView::cssFile. Можно также расширить класс CTabView, чтобы при использовании виджета не требовалась постоянная конфигурация, следующим образом:
class MyTabView extends CTabView
{
public function init()
{
if($this->cssFile===null)
{
$file=dirname(__FILE__).DIRECTORY_SEPARATOR.'tabview.css';
$this->cssFile=Yii::app()->getAssetManager()->publish($file);
}
parent::init();
}
}
Выше мы переопределяем метод CWidget::init и, если свойство CTabView::cssFile не установлено,
присваиваем ему значение URL нового CSS-стиля по умолчанию. Файл нового CSS-стиля необходимо поместить
в одну папку с файлом класса MyTabView
, чтобы их можно было упаковать как расширение. Поскольку CSS-стиль не доступен из веб, его
необходимо опубликовать как ресурс.
Чтобы написать виджет с нуля, нужно, как правило, реализовать два метода: CWidget::init и CWidget::run.
Первый метод вызывается, когда мы используем конструкцию $this->beginWidget
для вставки виджета в представление,
а второй - когда используется конструкция $this->endWidget
.
Если необходимо получить и обработать некоторый контент между вызовами этих двух функций
можно запустить буферизацию вывода в
CWidget::init и получать сохраненный вывод для дальнейшей обработки в методе CWidget::run.
На странице, где используется виджет, он обычно подключает CSS-стили, JavaScript файлы и прочие файлы ресурсов. Файлы такого рода называются ресурсы, поскольку хранятся с файлом класса виджета и, как правило, недоступны веб-пользователям. Для того, чтобы дать к ним доступ, их необходимо опубликовать, используя CWebApplication::assetManager, как показано в фрагменте кода выше. Помимо этого, если необходимо подключить файлы CSS-стиля или JavaScript на текущей странице, их необходимо зарегистрировать посредством CClientScript:
class MyWidget extends CWidget
{
protected function registerClientScript()
{
// ...publish CSS or JavaScript file here...
$cs=Yii::app()->clientScript;
$cs->registerCssFile($cssFile);
$cs->registerScriptFile($jsFile);
}
}
Виджет также может иметь собственные файлы представлений. В этом случае необходимо создать папку views
в папке с файлом класса виджета и поместить в нее все файлы представлений. Чтобы отрендерить представления виджета в его классе используется
конструкция $this->render('ViewName')
, аналогично использованию в контроллере.
Действие должно расширять класс CAction или производные от него. IAction::run - основной метод, который необходимо реализовать для действия.
Фильтр должен расширять класс CFilter или производные от него. Основными методами, которые необходимо реализоваться, являются CFilter::preFilter и CFilter::postFilter. Первый вызывается до выполнения действия, второй - после.
class MyFilter extends CFilter
{
protected function preFilter($filterChain)
{
// применяется до выполнения действия
return true; // значение false возвращается, если действие не должно выполняться
}
protected function postFilter($filterChain)
{
// применяется после завершения выполнения действия
}
}
Параметр $filterChain
- экземпляр класса CFilterChain, содержащий информацию о действии, к которому применяются фильтры в настоящий момент.
Контроллер, предлагаемый как расширение, должен наследовать класс CExtController, а не класс CController.
Основной причиной этого является то, что в случае класса CController предполагается, что файлы представлений располагаются
в application.views.ControllerID
, а в случае класса CExtController считается, что файлы представлений находятся в папке views
,
расположенной в папке с файлом класса этого контроллера. Очевидно, что расширение-контроллер удобнее распространять, когда все
файлы расширения собраны в одном месте.
Валидатор должен расширять класс CValidator и реализовывать его метод CValidator::validateAttribute.
class MyValidator extends CValidator
{
protected function validateAttribute($model,$attribute)
{
$value=$model->$attribute;
if($value has error)
$model->addError($attribute,$errorMessage);
}
}
Консольная команда должна расширять класс CConsoleCommand и реализовывать его метод CConsoleCommand::run. При желании можно переопределить метод CConsoleCommand::getHelp, который отвечает за информационную справку по команде.
class MyCommand extends CConsoleCommand
{
public function run($args)
{
// $args - массив аргументов, переданных с командой
}
public function getHelp()
{
return 'Usage: how to use this command';
}
}
Информация о порядке использования и создания модулей представлена в разделе Модуль.
Если сформулировать требования в общем виде, то модуль должен быть самодостаточным, файлы ресурсов (CSS, JavaScript, изображения), используемые модулем, должны распространяться вместе с модулем, а сам модуль должен публиковать ресурсы, чтобы они были доступны для веб-пользователей.
Разработка компонента общего вида аналогична написанию класса. Компонент, как и модуль, должен быть самодостаточен и удобен для использования разработчиками.
Signup or Login in order to comment.