Files
yii/docs/guide/ru/extension.create.txt
2010-11-14 14:17:44 +00:00

223 lines
15 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Создание расширений
===================
Поскольку создание расширений подразумевает их использование сторонними разработчиками,
процесс создания требует дополнительных усилий. Ниже приведены основные правила, которые необходимо соблюдать
при создании расширений:
* расширение должно быть самодостаточным, т.е. зависимость от внешних ресурсов должна быть минимальна. Очень неудобно, когда для работы
расширения требуется устанавливать дополнительные пакеты, классы и иные файлы ресурсов;
* все файлы расширения должны быть собраны в одной папке, имя которой должно совпадать с именем расширения;
* классы расширения должны начинаться с префикса, чтобы избежать конфликтов имен с классами других расширений;
* расширение должно включать подробную документацию по API и порядку установки, чтобы сократить время, необходимое для изучения и работы с расширением;
* расширение должно использовать подходящую лицензию. Если вы хотите, чтобы ваше расширение могло быть использовано как открытыми, так и закрытыми проектами,
вы можете воспользоваться лицензиями BSD, MIT и др., но не GPL, т.к. последняя требует, чтобы код, где было использовано ваше расширение, также был открыт.
Ниже мы расскажем о том, как создать новое расширение в соответствии с классификацией,
приведенной в [обзоре](/doc/guide/extension.overview). Пояснения в равной степени распространяются и на
расширения, используемые исключительно в собственных проектах.
Компонент приложения
---------------------
[Компонент приложения](/doc/guide/basics.application#application-component) должен реализовывать интерфейс [IApplicationComponent]
или расширять класс [CApplicationComponent]. Основной метод, который необходимо реализовать, — [IApplicationComponent::init].
В этом методе компонент инициализируется. Метод вызывается после того, как компонент создан и получены начальные значения,
обозначенные в [конфигурации приложения](/doc/guide/basics.application#application-configuration).
По умолчанию, компонент приложения создается и инициализируется только в момент первого обращения к нему в ходе обработки запроса.
Если необходимо принудительно создавать компонент сразу после создания экземпляра приложения, то нужно добавить идентификатор
этого компонента в свойство [CApplication::preload].
Поведение
---------
Для того, чтобы создать поведение необходимо реализовать интерфейс [IBehavior].
Для удобства в Yii имеется класс [CBehavior], реализующий этот интерфейс и
предоставляющий некоторые общие методы. Наследуемые классы могут реализовать
дополнительные методы, которые будут доступны в компонентах, к которым прикреплено
поведение.
При разработке поведений для [CModel] и [CActiveRecord] можно наследовать
[CModelBehavior] и, соответственно, [CActiveRecordBehavior]. Эти базовые классы
предоставляют дополнительные возможности, специально созданные для [CModel] и [CActiveRecord].
К примеру, класс [CActiveRecordBehavior] реализует набор методов для обработки
событий жизненного цикла ActiveRecord. Наследуемый класс, таким образом, может
перекрыть эти методы и выполнить код, участвующий в жизненном цикле AR.
Следующий код демонстрирует пример поведения ActiveRecord. Если это поведение
назначено объекту AR и вызван метод `save()`, атрибутам `create_time` и
`update_time` будет автоматически выставлено текущее время.
~~~
[php]
class TimestampBehavior extends CActiveRecordBehavior
{
public function beforeSave($event)
{
if($this->owner->isNewRecord)
$this->owner->create_time=time();
else
$this->owner->update_time=time();
}
}
~~~
Виджет
------
[Виджет](/doc/guide/basics.view#widget) должен расширять класс [CWidget] или производные от него.
Наиболее простой способ создать виджет — расширить существующий виджет и переопределить его методы или заменить значения по умолчанию.
Например, если вы хотите заменить CSS-стиль для [CTabView], то, используя виджет, нужно сконфигурировать свойство [CTabView::cssFile]. Можно также расширить класс
[CTabView], чтобы при использовании виджета не требовалась постоянная конфигурация, следующим образом:
~~~
[php]
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`.
Если необходимо получить и обработать некоторый контент между вызовами этих двух функций
можно запустить [буферизацию вывода](http://php.net/manual/en/book.outcontrol.php) в
[CWidget::init] и получать сохраненный вывод для дальнейшей обработки в методе [CWidget::run].
На странице, где используется виджет, он обычно подключает CSS-стили, JavaScript файлы и прочие файлы ресурсов.
Файлы такого рода называются *ресурсы*, поскольку хранятся с файлом класса виджета и, как правило, недоступны веб-пользователям.
Для того, чтобы дать к ним доступ, их необходимо опубликовать, используя [CWebApplication::assetManager], как показано в фрагменте кода выше.
Помимо этого, если необходимо подключить файлы CSS-стиля или JavaScript на текущей странице, их необходимо зарегистрировать посредством [CClientScript]:
~~~
[php]
class MyWidget extends CWidget
{
protected function registerClientScript()
{
// …подключаем здесь файлы CSS или JavaScript…
$cs=Yii::app()->clientScript;
$cs->registerCssFile($cssFile);
$cs->registerScriptFile($jsFile);
}
}
~~~
Виджет также может иметь собственные файлы представлений. В этом случае необходимо создать папку `views`
в папке с файлом класса виджета и поместить в нее все файлы представлений. Чтобы отрендерить представления виджета в его классе используется
конструкция `$this->render('ViewName')`, аналогично использованию в контроллере.
Действие
------
[Действие](/doc/guide/basics.controller#action) должно расширять класс [CAction] или производные от него. [IAction::run] — основной метод, который необходимо
реализовать для действия.
Фильтр
------
Фильтр должен расширять класс [CFilter] или производные от него. Основными методами, которые необходимо реализовать,
являются [CFilter::preFilter] и [CFilter::postFilter]. Первый вызывается до выполнения действия, второй — после.
~~~
[php]
class MyFilter extends CFilter
{
protected function preFilter($filterChain)
{
// применяется до выполнения действия
return true; // значение false возвращается, если действие не должно выполняться
}
protected function postFilter($filterChain)
{
// применяется после завершения выполнения действия
}
}
~~~
Параметр `$filterChain` — экземпляр класса [CFilterChain], содержащий информацию о действии, к которому применяются фильтры в настоящий момент.
Контроллер
----------
[Контроллер](/doc/guide/basics.controller), предлагаемый как расширение, должен наследовать класс [CExtController], а не класс [CController].
Основной причиной этого является то, что в случае класса [CController] предполагается, что файлы представлений располагаются
в `application.views.ControllerID`, а в случае класса [CExtController] считается, что файлы представлений находятся в папке `views`,
расположенной в папке с файлом класса этого контроллера. Очевидно, что расширение-контроллер удобнее распространять, когда все
файлы расширения собраны в одном месте.
Валидатор
---------
Валидатор должен расширять класс [CValidator] и реализовывать его метод [CValidator::validateAttribute].
~~~
[php]
class MyValidator extends CValidator
{
protected function validateAttribute($model,$attribute)
{
$value=$model->$attribute;
if($value has error)
$model->addError($attribute,$errorMessage);
}
}
~~~
Команда консоли
---------------
[Консольная команда](/doc/guide/topics.console) должна расширять класс [CConsoleCommand]
и реализовывать его метод [CConsoleCommand::run]. При желании можно переопределить
метод [CConsoleCommand::getHelp], который отвечает за информационную справку по команде.
~~~
[php]
class MyCommand extends CConsoleCommand
{
public function run($args)
{
// $args — массив аргументов, переданных с командой
}
public function getHelp()
{
return 'Usage: how to use this command';
}
}
~~~
Модуль
------
Информация о порядке использования и создания модулей представлена в разделе [Модуль](/doc/guide/basics.module#using-module).
Если сформулировать требования в общем виде, то модуль должен быть самодостаточным, файлы ресурсов (CSS, JavaScript, изображения), используемые модулем, должны распространяться вместе с модулем, а сам модуль должен публиковать ресурсы, чтобы они были доступны для веб-пользователей.
Компонент общего вида
-----------------
Разработка компонента общего вида аналогична написанию класса. Компонент, как и модуль,
должен быть самодостаточен и удобен для использования разработчиками.
<div class="revision">$Id: extension.create.txt 1423 2009-09-28 01:54:38Z qiang.xue $</div>