среда, 7 декабря 2011 г.

Некоторые моменты создания и работы модуля в Yii

Предисловие

Данный материал не претендует на оригинальность, скорее всего это просто ход мыслей при освоении работы с модулями в Yii Framework. Всё дальнейшее можно воспринимать как попытку расширить некоторые моменты, описанные сухим языком справочной системы.

Материал предназначен для людей только начавших осваивать Yii Framework.


Создание модуля

Если структура приложения Yii была создана с использованием утилиты yiic, то самый удобный и простой способ создать модуль в Yii — воспользоваться кодогенератором Gii, который в общем случае может быть вызван по URL

http://[сервер]/[путь_к_приложению]/index.php?r=gii

При этом модуль Gii должен быть подключен и настроен в конфигурационном файле приложения main.php. Для генерации модуля в меню на странице кодогенератора выбирается Module Generator, затем вводится уникальный идентификатор, он же — имя, модуля.

Идентификатор модуля должен содержать только буквенные символы, при этом он зависит от регистра символов, то есть «example» не то же самое, что «Example». Это написано во всплывающей подсказке при установке курсора в поле Module ID на странице создания модуля.

Структура каталогов будущего модуля, которая будет сгенерирована, видна уже после нажатия Preview. Если, например, имя модуля «example», структура формируется следующая:

 modules
 |-example
   |-ExampleModule.php
   |
   |-components
   |-controllers
   | |-DefaultController.php
   |
   |-messages
   |-models
   |-views
     |-default
     | |-index.php
     |
     |-layouts
где:
  • modules — стандартный каталог приложения;
  • example — каталог с именем модуля (то, что было введено в Module ID);
  • ExampleModule.php — файл класса модуля, имя которого зависит от имени модуля, только с заглавной буквы;
  • components - может содержать компоненты пользователя;
  • controllers - содержит файлы классов контроллеров;
  • DefaultController.php – контроллер по умолчанию при создании модуля;
  • models - содержит файлы классов моделей;
  • views - содержит файлы представлений контроллера и макетов;
  • default - содержит файлы представлений для контроллера по умолчанию (DefaultController);
  • index.php — начальное представление для модуля;
  • layouts — содержит файлы макетов.

После нажатия Generate будет сгенерирована структура модуля, о чём появится соответствующее сообщение. Будет так же сообщено о том, что для того, чтобы модуль заработал его нужно прописать в конфигурационном файле приложения main.php ([путь_к_приложению]/protected/config/main.php).

Если модуль Gii по каким-то причинам недоступен, то создать структуру модуля можно даже вручную воспользовавшись описанием структуры, приведённой выше или взятой из описания модуля в справочной системе.

Чтобы прописать модуль в main.php необходимо в массив modules добавить значение '[имя модуля]':

<?php
...
  return array(
  ...
    'modules' => array(
      'example'
    ),
  ...
  );

При начальной генерации приложения утилитой yiic массив modules конфигурационного файла уже содержит что-то вроде следующего

'modules' => array(
  //uncomment the following to enable the Gii tool
  'gii' => array(
    'class' => 'system.gii.GiiModule',
    'password' => '********',
    //If removed, Gii defaults to localhost only. Edit carefully to taste.
    'ipFilters' => array('127.0.0.1','::1'),
  ),
),

То есть, как минимум один модуль уже прописан в приложении (Gii). Таким образом, после добавления информации о модуле 'example' код в этом случае вероятно будет таким:

'modules' => array(
  //uncomment the following to enable the Gii tool
  'gii' => array(
    'class' => 'system.gii.GiiModule',
    'password' => '********',
    //If removed, Gii defaults to localhost only. Edit carefully to taste.
    'ipFilters' => array('127.0.0.1','::1'),
  ),
  'example',
),

Теперь можно отобразить первую страницу модуля (index.php) используя URL: http://[сервер]/[путь_к_приложению]/index.php?r=example


Контроллеры и действия

При обращении к модулю, созданному по стандартной классической схеме, следующие записи в URL равнозначны:

.../index.php?r=example

.../index.php/?r=example/defalut

.../index.php/?r=example/default/index

В первом случае Yii в модуле example обращается к контроллеру по умолчанию ('default'), а в контроллере по умолчанию выполняется действие по умолчанию ('index').
При второй записи выполняется действие по умолчанию ('index') в указанном явно контроллере ('default').
В третьей записи контроллер и действие указаны явно в стандартом для Yii формате записи r=[модуль]/[контроллер]/[действие].

Если контроллер и (или) действие отличаются от определённых по умолчанию, то их всегда необходимо указывать явно (предположим, что существуют действие 'run' в контроллере по умолчанию 'default', а также контроллер 'worker' и действие в нём 'go'):

.../index.php?r=example/default/run

.../index.php?r=example/worker

.../index.php?r=example/worker/go

В первом случае вызывается действие, отличное от по умолчанию ('run'), в контроллере по умолчанию ('default');
Во втором — действие по умолчанию 'index' в контроллере 'worker', отличном от по умолчанию;
В третьем — действие, отличное от по умолчанию 'go', в контроллере, отличном от по умолчанию 'worker'.

При этом следует понимать, что контроллер по умолчанию, задаваемый для модуля, и действие по умолчанию, задаваемое для контроллера могут быть переопределены. Логично, что контроллер по умолчанию необходимо переопределить в классе модуля (ExampleModule в данном случае), а действия по умолчанию — в классах контроллеров (если основываться на предыдущих примерах, то это DefaultController и WorkerController). Класс модуля унаследован от стандартного класса Yii CWebModule, в котором определён контроллер по умолчанию:

public $defaultController = 'default';

Таким образом, чтобы переопределить контроллер по умолчанию в собственном модуле, необходимо просто изменить значение переменной $defaultController в классе модуля:

class ExampleModule extends CWebModule
{
  public $defaultController = 'worker';

  ...
}

После этого при использовании в URL .../index.php/?r=example будет происходить обращение к контроллеру worker (класс WorkerController) и вызываться в нём действие по умолчанию index (метод actionIndex), если, конечно, таковое существует в контроллере или не переопределено в контроллере.
Если действие не существует, или если действие по умолчанию не переопределялось и при этом действие 'index' не существует, то при обращении к контроллеру выходит ошибка 404 с сообщением о невозможности найти запрашиваемое действие.

Аналогично контроллеру по умолчанию для модуля, определяется действие по умолчанию в контроллере. В родительском классе для всех контроллеров CController это прописано в переменной $defaultAction:

public $defaultAction='index';

Таким образом, переписав в классе контроллера значение переменной $defaultAction, можно переопределить действие по умолчанию:

class WorkerController extends Controller
{
  public $defaultAction = 'go';
  ...
}

После переопределения контроллера по умолчанию и действия по умолчанию в этом контроллере, как приведено в примерах выше, следующие фрагменты URL приведут к одному и тому же результату:

.../index.php?r=example

.../index.php/?r=example/worker

.../index.php/?r=example/worker/go


Представления

Правила работы с представлениями в модуле, аналогичны правилам работы с представлениями в приложении. То есть представления, к которым обращается метод render() из контроллера, должны находиться в каталоге views/[имя_контроллера] модуля, а имена представлений должны совпадать с именем файла php представления. Так, если продолжать предыдущий пример с созданием контроллера worker, то файлы представлений, к которым обращаются из методов этого контроллера должны располагаться в каталоге modules/views/worker. И если разместить в указанном каталоге файл представления, например, go_page.php, то код вызова этого представления может быть следующим:

class WorkerController extends Controller
{
  public function actionGo()
  {
    $this->render('go_page');
  }
}

Начальные значения свойств модуля

При указании информации о модуле в файле настройки приложения main.php можно указать начальные значения свойств модуля. Например, в модуле gii заданы начальные значения свойств password и ipFilters. По этой же аналогии могут указываться начальные значения своего модуля:

'modules' => array(
  'example' => array(
    'headline' => 'Модуль для примера',
  ),
)

Само свойство headline при этом должно быть объявлено в классе модуля:

class ExampleModule extends CwebModule
{
  public $headline = '';
  ...
}

Обращаться к свойству модуля можно через свойство module контроллера. Например, в представлении, вызванном из контроллера модуля можно вывести заголовок модуля, указанный в main.php:

<?php echo $this->module->headline; ?>

Псевдоним пути для модуля

Yii определяет псевдоним пути при создании модуля соответствующий идентификатору модуля. Так, например, в примере с модулем example можно обращаться к каталогам и файлам внутри модуля при помощи псевдонима example, тогда псевдоним

example.controllers

будет соответствовать пути

[путь_к_приложению]\protected\modules\example\controllers

Так же можно импортировать классы используя псевдоним модуля:

Yii::import('example.models.ExampleForm');

Это подключит файл класса модели формы (ExampleForm.php), при наличии такового в подкаталоге models модуля, при первом обращении к этому классу.

При создании модуля с использованием кодогенератора Gii в методе init класса модуля Yii автоматически импортирует все классы в подкаталогах models и components модуля:

public function init()
{
  $this->setImport(
    array(
      'example.models.*',
      'example.components.*',
    )
  );
}

Ссылки на использованные ресурсы

  1. Русскоязычное сообщество Yii
  2. Официальная страница Yii Framework