Files
yii/docs/guide/ru/extension.create.txt
2012-03-05 20:37:50 -05: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>