Модули
Модули представляют собой автономные программные единицы, состоящие из моделей, представлений, контроллеров и других поддерживающих компонентов. Пользователи могут получить доступ к контроллерам модуля при его установке в приложении. По этим причинам модули часто рассматриваются как мини-приложения. Модули отличаются от приложений тем, что модули не могут развертываться самостоятельно и должны находиться внутри приложений.
Создание модулей
Модуль организован как директория, которая называется базовым путем модуля. Внутри директории есть поддиректории, такие как controllers, models, views, которые содержат контроллеры, модели, представления и другой код, как и в приложении. Следующий пример демонстрирует содержимое модуля:
forum/
Module.php the module class file
controllers/ containing controller class files
DefaultController.php the default controller class file
models/ containing model class files
views/ containing controller view and layout files
layouts/ containing layout view files
default/ containing view files for DefaultController
index.php the index view file
Классы модулей
Каждый модуль должен иметь уникальный класс модуля, который расширяет yii\base\Module. Класс должен располагаться непосредственно под базовым путем модуля и должен быть загружаемым. При доступе к модулю будет создан единственный экземпляр соответствующего класса модуля. Как и экземпляры приложения, экземпляры модулей используются для совместного использования данных и компонентов для кода внутри модулей.
Следующий пример демонстрирует, как может выглядеть класс модуля:
namespace app\modules\forum;
class Module extends \yii\base\Module
{
public function init()
{
parent::init();
$this->params['foo'] = 'bar';
// ... other initialization code ...
}
}
Если метод init() содержит много кода для инициализации свойств модуля, вы можете сохранить их в виде конфигурации и загрузить её следующим кодом в init():
public function init()
{
parent::init();
// initialize the module with the configuration loaded from config.php
\Yii::configure($this, require(__DIR__ . '/config.php'));
}
где конфигурационный файл config.php может содержать следующий контент, аналогичный контенту в конфигурации приложения.
<?php
return [
'components' => [
// list of component configurations
],
'params' => [
// list of parameters
],
];
Контроллеры в модулях
При создании контроллеров в модуле принято размещать классы контроллеров в подпространстве controllers пространства имён класса модуля. Это также означает, что файлы классов контроллеров должны быть размещены в директории controllers внутри базового пути модуля. Например, чтобы создать контроллер post в модуле forum , показанном в последнем подразделе, вы должны объявить класс контроллера следующим образом:
namespace app\modules\forum\controllers;
use yii\web\Controller;
class PostController extends Controller
{
// ...
}
Вы можете настроить пространство имён классов контроллеров, настроив свойство yii\base\Module::$controllerNamespace. В случае, если некоторые контроллеры находятся вне этого пространства имён, вы можете сделать их доступными, настроив свойство yii\base\Module::$controllerMap, аналогично тому, что вы делаете в приложении.
Представления в модулях
Представления в модуле должны быть размещены в директории views внутри базового пути модуля. Для представлений, рендер которых выполняется контроллером в модуле, они должны быть размещены в директории views/ControllerID, где ControllerID относится к идентификатору контроллера. Например, если класс контроллера PostController, директория будет views/post внутри базового пути модуля.
Модуль может указать макет, который применяется к представлениям, рендер которых выполняется контроллерами модуля. Макет должен быть помещён в директорию views/layouts по умолчанию, и вы должны настроить свойство yii\base\Module::$layout для указания имени макета. Если вы не настроите свойство layout, будет использован макет приложения.
Команды консоли в модулях
Ваш модуль также может объявлять команды, которые будут доступны через режим Консоли.
Для того, чтобы утилита командной строки видела ваши команды, вам необходимо изменить свойство yii\base\Module::$controllerNamespace при выполнении Yii в режиме консоли и указать его на пространство имён ваших команд.
Один из способов достижения этого - проверить тип экземпляра приложения Yii в методе init() модуля:
public function init()
{
parent::init();
if (Yii::$app instanceof \yii\console\Application) {
$this->controllerNamespace = 'app\modules\forum\commands';
}
}
Тогда ваши команды будут доступны из командной строки с помощью следующего маршрута:
yii <module_id>/<command>/<sub_command>
Использование модулей
Чтобы использовать модуль в приложении, просто настройте приложение, перечислив модуль в свойстве modules приложения. Следующий код в конфигурации приложения использует модуль forum:
[
'modules' => [
'forum' => [
'class' => 'app\modules\forum\Module',
// ... other configurations for the module ...
],
],
]
Свойство modules принимает массив конфигураций модулей. Каждый ключ массива представляет собой идентификатор модуля, который однозначно идентифицирует модуль среди всех модулей в приложении, а соответствующее значение массива — это конфигурация для создания модуля.
Маршруты
Как и при доступе к контроллерам в приложении, маршруты используются для адресации контроллеров в модуле. Маршрут для контроллера внутри модуля должен начинаться с идентификатора модуля, за которым следуют идентификатор контроллера и идентификатор действия. Например, если приложение использует модуль с именем forum, то маршрут forum/post/index будет представлять действие index контроллера post в модуле. Если маршрут содержит только идентификатор модуля, то свойство yii\base\Module::$defaultRoute, которое по умолчанию равно default, определит, какой контроллер/действие следует использовать. Это означает, что маршрут forum будет представлять контроллер default в модуле forum.
Доступ к модулям
Внутри модуля вам часто может потребоваться получить экземпляр класса модуля, чтобы получить доступ к идентификатору модуля, параметрам модуля, компонентам модуля и т.д. Вы можете сделать это с помощью следующего оператора:
$module = MyModuleClass::getInstance();
где MyModuleClass — это имя класса модуля, который вас интересует. Метод getInstance() вернёт текущий запрашиваемый экземпляр класса модуля. Если модуль не запрошен, метод вернёт null. Обратите внимание, что вам не следует вручную создавать новый экземпляр класса модуля, так как он будет отличаться от экземпляра, созданного Yii в ответ на запрос.
Информация: При разработке модуля не следует предполагать, что модуль будет использовать фиксированный идентификатор. Это связано с тем, что модуль может быть связан с произвольным идентификатором при использовании в приложении или в другом модуле. Для получения идентификатора модуля необходимо сначала получить экземпляр модуля с помощью вышеописанного подхода, а затем получить идентификатор через
$module->id.
Вы также можете получить доступ к экземпляру модуля с помощью следующих подходов:
// get the child module whose ID is "forum"
$module = \Yii::$app->getModule('forum');
// get the module to which the currently requested controller belongs
$module = \Yii::$app->controller->module;
Первый подход полезен только в том случае, если вам известен идентификатор модуля, а второй подход лучше использовать, когда вам известны запрашиваемые контроллеры.
После получения экземпляра модуля вы можете получить доступ к параметрам и компонентам, зарегистрированным в модуле. Например,
$maxPostCount = $module->params['maxPostCount'];
Инициализация модулей
Некоторые модули могут потребоваться для каждой заявки. Например, это модуль отладки. Для этого перечислите идентификаторы таких модулей в свойстве bootstrap приложения.
Например, следующая конфигурация приложения гарантирует, что модуль debug всегда загружается:
[
'bootstrap' => [
'debug',
],
'modules' => [
'debug' => 'yii\debug\Module',
],
]
Вложенные модули
Модули могут быть вложены на неограниченном уровне. То есть модуль может содержать другой модуль, который может содержать ещё один модуль. Первый модуль называется родительским модулем, а второй — дочерним модулем. Дочерние модули должны быть объявлены в свойстве modules своих родительских модулей. Например,
namespace app\modules\forum;
class Module extends \yii\base\Module
{
public function init()
{
parent::init();
$this->modules = [
'admin' => [
// you should consider using a shorter namespace here!
'class' => 'app\modules\forum\modules\admin\Module',
],
];
}
}
Для контроллера внутри вложенного модуля его маршрут должен включать идентификаторы всех его родительских модулей. Например, маршрут forum/admin/dashboard/index представляет действие index контроллера dashboard в модуле admin, который является дочерним модулем модуля forum.
Информация: Метод getModule() возвращает только дочерний модуль, непосредственно принадлежащий его родителю. Свойство yii\base\Application::$loadedModules хранит список загруженных модулей, включая как непосредственных дочерних, так и вложенных, индексированных по их именам классов.
Рекомендации по разработке
Модули лучше всего использовать в крупных приложениях, чьи функции можно разделить на несколько групп, каждая из которых состоит из набора тесно связанных функций. Каждая такая группа функций может быть разработана как модуль, который разрабатывается и поддерживается конкретным разработчиком или командой.
Модули также являются хорошим способом повторного использования кода на уровне группы функций. Некоторые часто используемые функции, такие как управление пользователями, управление комментариями, могут быть разработаны в виде модулей, чтобы их можно было легко повторно использовать в будущих проектах.
© 2008–2017 by Yii Software LLC
Licensed under the three clause BSD license.
http://www.yiiframework.com/doc-2.0/guide-structure-modules.html