mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-12 11:06:54 +01:00
174 lines
14 KiB
Plaintext
174 lines
14 KiB
Plaintext
Створення розширень
|
||
===================
|
||
|
||
Оскільки створення розширень передбачає їх використання сторонніми розробниками, процес створення вимагає додаткових зусиль. Нижче наведені основні правила, яких необхідно дотримуватися при створенні розширень:
|
||
|
||
* розширення повинно бути самодостатнім, тобто залежність від зовнішніх ресурсів повинна бути мінімальна. Дуже незручно, коли для роботи розширення потрібно встановлювати додаткові пакети, класи та інші файли ресурсів;
|
||
* всі файли розширення повинні бути зібрані в одній директорії, імʼя якої має збігатися із назвою розширення;
|
||
* класи розширення повинні починатися з префікса, щоб уникнути конфліктів імен з класами інших розширень;
|
||
* розширення повинно включати детальну документацію по 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> |