Оскільки створення розширень передбачає їх використання сторонніми розробниками, процес створення вимагає додаткових зусиль. Нижче наведені основні правила, яких необхідно дотримуватися при створенні розширень:
Нижче ми розповімо про те, як створити нове розширення відповідно до класифікації, наведеної в огляді. Пояснення в рівній мірі поширюються і на розширення, які використовуються виключно у власних проектах.
Компонент додатка повинен реалізовувати інтерфейс 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()
{
// …підключаємо тут файли CSS або JavaScript…
$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, зображення), що використовуються модулем, повинні поширюватися разом з модулем, а сам модуль повинен публікувати ресурси, щоб вони були доступні для веб-користувачів.
Розробка загального компонента аналогічна написання класу. Компонент, як і модуль, повинен бути самодостатнім і зручним для використання розробниками.
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.