Починаючи з версії 1.1.2, до складу Yii входить веб-інструмент для генерації коду, який називається Gii.
Він замінює консольний генератор yiic shell
, що існував до цього.
У даному розділі описано, як використовувати Gii і як розширити його для прискорення розробки.
Gii є модулем і повинен бути використаний у складі існуючого додатка Yii. Для використання Gii необхідно відредагувати файл конфігурації додатка наступним чином:
return array(
…
'modules'=>array(
'gii'=>array(
'class'=>'system.gii.GiiModule',
'password'=>'задайте свій пароль',
// 'ipFilters'=>array(…перелік IP…),
// 'newFileMode'=>0666,
// 'newDirMode'=>0777,
),
),
);
Вище ми оголосили модуль з імʼям gii
і класом GiiModule.
Також ми встановили пароль, який буде використовуватися для доступу до Gii.
За умовчанням, у цілях безпеки, Gii доступний тільки для localhost. Якщо необхідно надати доступ до нього з інших компʼютерів, потрібно встановити властивість GiiModule::ipFilters як показано в коді вище.
Так як Gii буде генерувати і зберігати нові файли з кодом в існуючий додаток, необхідно переконатися в тому, що процес веб-сервера має на це права. Показані вище властивості GiiModule::newFileMode та GiiModule::newDirMode містять права, з якими будуть створюватися файли і директорії.
Примітка: Gii є інструментом розробника. Тому він повинен бути встановлений виключно на компʼютері або сервері розробника. Так як він може генерувати нові скрипти PHP, необхідно приділити особливу увагу безпеці (пароль, IP фільтри).
Тепер можна запустити Gii по URL http://hostname/path/to/index.php?r=gii
,
де http://hostname/path/to/index.php
- URL вашого додатку.
Якщо існуючий додаток використовує формат URL path
(див. гарні адреси URL),
ми можемо запустити Gii по URL http://hostname/path/to/index.php/gii
.
Може знадобитися додати наступні правила URL перед вже існуючими:
'components'=>array(
…
'urlManager'=>array(
'urlFormat'=>'path',
'rules'=>array(
'gii'=>'gii',
'gii/<controller:\w+>'=>'gii/<controller>',
'gii/<controller:\w+>/<action:\w+>'=>'gii/<controller>/<action>',
…існуючі правила…
),
),
)
У складі Gii є готовий набір генераторів коду. Кожен генератор відповідає за свій тип коду. Наприклад, генератор контролера створює клас контролера разом з декількома шаблонами представлення; генератор моделі створює клас ActiveRecord для певної таблиці БД.
Послідовність роботи з генератором наступна:
Preview
для попередньої оцінки генерованого коду.
Ви побачите таблицю файлів, які будуть згенеровані і зможете переглянути їх код;Generate
для створення файлів;Примітка: після генерації моделі варто перевірити і скоригувати метод
rules
, так як структура бази даних часто не містить достатньо даних про вимоги валідації.
Незважаючи на те, що включені до складу Gii генератори створюють досить функціональний код, часто потрібно його трохи змінити або створити новий генератор на свій смак та потреби. Приміром, нам може знадобитися змінити стиль генерованого коду або додати підтримку кількох мов. Все це може бути легко реалізовано через Gii.
Gii можна розширювати двома способами: змінюючи існуючі шаблони кодогенераторів та створюючи свої генератори.
Генератор коду розміщується в директорії, чиє імʼя є імʼям генератора. Директорія зазвичай містить:
model/ коренева директорія генератора моделі ModelCode.php модель, яка використовується для генерації коду ModelGenerator.php контролер кодогенератора views/ представлення генератора index.php шаблон за замовчуванням templates/ шаблони коду default/ набір шаблонів 'default' model.php шаблон для генерації класу моделі
Gii шукає генератори у списку директорій, зазначених у властивості GiiModule::generatorPaths. У тому випадку, якщо необхідно додати свої генератори, слід налаштувати додаток таким чином:
return array(
'modules'=>array(
'gii'=>array(
'class'=>'system.gii.GiiModule',
'generatorPaths'=>array(
'common.gii', // псевдонім шляху
),
),
),
);
Наведені вище налаштування змушують Gii шукати генератори в директорії із псевдонімом common.gii
на додаток до стандартного system.gii.generators
та application.gii
.
Можливо мати кілька однойменних генераторів, якщо у них різні шляхи пошуку. У цьому випадку буде використовуватися генератор, шлях пошуку якого зазначений вище в GiiModule::generatorPaths.
Зміна шаблонів коду - найпростіший і найпоширеніший шлях розширення Gii. Ми будемо використовувати приклади для того, щоб описати, як змінити шаблони коду. Припустимо, нам необхідно змінити код, що створюється генератором моделі.
Спочатку ми створюємо директорію protected/gii/model/templates/compact
.
Тут model
означає, що ми збираємося перекрити генератор моделі за замовчуванням.
А templates/compact
- що ми додаємо новий набір шаблонів коду compact
.
Після цього ми додаємо в налаштування програми у властивість
GiiModule::generatorPaths значення application.gii
, як показано у попередньому підрозділі.
Тепер відкриваємо сторінку генератора моделі. Клацаємо на поле Code Template
.
Ви повинні побачити список, що випадає, який містить нашу щойно створену директорію шаблонів compact
.
Проте, якщо ми оберемо цей шаблон, буде виведена помилка.
Відбувається це тому, що у наборі compact
ще немає самих шаблонів коду.
Скопіюємо файл framework/gii/generators/model/templates/default/model.php
в protected/gii/model/templates/compact
. Якщо спробувати згенерувати код з набором compact
ще раз,
генерація повинна пройти успішно. Тим не менш, генерований код нічим не відрізняється від коду,
який одержується з набору default
.
Час зробити деякі зміни. Відкриємо файл protected/gii/model/templates/compact/model.php
.
Даний файл буде використано як шаблон представлення, що означає, що він може містити вирази і код PHP.
Змінимо шаблон таким чином, що метод attributeLabels()
генерованого коду буде використовувати Yii::t()
для перекладу заголовків полів:
public function attributeLabels() { return array( foreach($labels as $name=>$label): echo "'$name' => Yii::t('application', '$label'),\n"; endforeach; ); }
У кожному шаблоні коду у нас є доступ до деяких визначених змінних, таких як, наприклад, $labels
.
Ці змінні задаються відповідним генератором коду. Різні генератори можуть надавати шаблонам різні набори змінних.
Варто уважно вивчити опис шаблонів коду за замовчуванням.
У цьому підрозділі ми покажемо, як реалізувати новий генератор, який зможе створювати нові класи віджетів.
Спочатку створимо директорію protected/gii/widget
. У ній створимо такі файли:
WidgetGenerator.php
: містить клас контролера WidgetGenerator
, який є вхідною точкою генератора віджетів.WidgetCode.php
: містить клас моделі WidgetCode
, який відповідає за логіку генерації коду.views/index.php
: відображення, що містить форму введення генератора.templates/default/widget.php
: шаблон коду за замовчуванням для генерації класу віджета.WidgetGenerator.php
Файл WidgetGenerator.php
вкрай простий. Він містить лише наступний код:
class WidgetGenerator extends CCodeGenerator
{
public $codeModel='application.gii.widget.WidgetCode';
}
Тут ми описуємо, що генератор буде використовувати клас моделі,
чий псевдонім шляху application.gii.widget.WidgetCode
.
Клас WidgetGenerator
успадковується від CCodeGenerator, що реалізує велику кількість функцій,
включаючи дії контролера, необхідні для координації процесу генерації коду.
WidgetCode.php
Файл WidgetCode.php
містить клас моделі WidgetCode
,
у якому реалізована логіка генерації класу віджету на основі отриманих від користувача параметрів.
У даному прикладі будемо вважати, що єдине,
що вводить користувач — імʼя класу віджета. WidgetCode
виглядає наступним чином:
class WidgetCode extends CCodeModel
{
public $className;
public function rules()
{
return array_merge(parent::rules(), array(
array('className', 'required'),
array('className', 'match', 'pattern'=>'/^\w+$/'),
));
}
public function attributeLabels()
{
return array_merge(parent::attributeLabels(), array(
'className'=>'Widget Class Name',
));
}
public function prepare()
{
$path=Yii::getPathOfAlias('application.components.' . $this->className) . '.php';
$code=$this->render($this->templatepath.'/widget.php');
$this->files[]=new CCodeFile($path, $code);
}
}
Клас WidgetCode
успадковується від CCodeModel. Як і в звичайному класі моделі,
в даному класі ми реалізуємо методи rules()
і attributeLabels()
для валідації введення і
генерації підписів полів відповідно. Варто зазначити, що так як базовий клас CCodeModel
вже описує деяку кількість правил валідації і назв підписів,
то ми повинні обʼєднати їх з нашими правилами і підписами.
Метод prepare()
готує код до генерації. Головне завдання методу - підготувати список обʼєктів CCodeFile,
кожен з яких представляє майбутній файл з кодом.
У нашому прикладі необхідно створити всього один обʼєкт CCodeFile, що представляє клас віджету,
який буде згенеровано в директорії protected/components
. Для безпосередньої генерації коду
використовується метод CCodeFile::render. Даний метод містить PHP-шаблон коду і повертає згенерований код.
views/index.php
Після реалізації контролера (WidgetGenerator
) і моделі (WidgetCode
)
саме час зайнятися представленням views/index.php
:
<h1>Генератор віджета</h1> $form=$this->beginWidget('CCodeForm', array('model'=>$model)); <div class="row"> echo $form->labelEx($model,'className'); echo $form->textField($model,'className',array('size'=>65)); <div class="tooltip"> Клас віджета повинен містити тільки літери. </div> echo $form->error($model,'className'); </div> $this->endWidget();
У даному коді ми відображаємо форму, використовуючи віджет CCodeForm.
У цій формі ми показуємо поле для введення атрибута className
моделі WidgetCode
.
При створенні форми ми можемо використовувати дві чудові можливості CCodeForm. Одна - підказки для полів. Друга - запамʼятовування введених значень.
Якщо ви використали один із стандартних генераторів коду, ви могли помітити гарні спливаючі підказки,
що зʼявляються поруч із полем при отриманні ним фокусу.
Використовувати дану можливість дуже легко: достатньо після поля вкласти div
з CSS класом tooltip
.
Для деяких полів корисно запамʼятати останнє вірне значення і тим самим дозволивши користувачеві не вводити значення повторно щоразу, коли він використовує генератор. Прикладом може служити поле введення базового класу контролера у стандартному генераторі. Такі поля спочатку відображаються як підсвічений статичний текст. При натисканні вони перетворюються в поля введення.
Для того, щоб запамʼятовувати ці дані, необхідно зробити дві речі.
По-перше, потрібно описати правило валідації sticky
для відповідного атрибута моделі.
Приміром, для стандартного генератора контролера використовується наведене нижче правило
для запамʼятовування атрибутів baseClass
і actions
:
public function rules()
{
return array_merge(parent::rules(), array(
…
array('baseClass, actions', 'sticky'),
));
}
По-друге, у відображенні необхідно додати CSS клас sticky
контейнеру div
поля вводу:
<div class="row sticky">
…поле введення…
</div>
templates/default/widget.php
Нарешті, ми створюємо шаблон коду templates/default/widget.php
. Як було описано раніше,
він використовується як PHP-шаблон представлення. У шаблоні коду ми завжди можемо звернутися до змінної $this
,
яка містить екземпляр моделі коду. У нашому прикладі $this
містить обʼєкт WidgetModel
.
Таким чином, ми можемо отримати введений користувачем клас віджету через $this->className
.
echo '<?php'; class echo $this->className; extends CWidget { public function run() { } }
На цьому реалізація генератора коду завершена.
Звернутися до нього можна по URL http://hostname/path/to/index.php?r=gii/widget
.
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.