Модули в Yii 2: структура папок и правильное подключение
Как собрать модуль в Yii 2 из файлов, зарегистрировать его в конфигурации и заставить работать маршруты вида /admin/user/index — с реальной структурой каталогов и типичными ошибками bootstrap.

Вы добавили класс модуля, прописали его в components вместо modules, и Yii отдаёт 404 на любом маршруте внутри. Или модуль зарегистрирован, но контроллер не находится, потому что namespace в файле не совпадает с тем, что Yii ждёт по PSR-4. Разберём, как устроен модуль в Yii 2 (актуально для 2.0.x, проверено на 2.0.49), из каких обязательных частей он состоит и как подключить его так, чтобы заработали и маршруты, и слои, и bootstrap.
Модуль в Yii 2 — это мини-приложение внутри приложения: свои контроллеры, представления, модели, иногда своя конфигурация и слои (виджеты, компоненты). Типичный сценарий — админка, которую хочется вынести из общего пространства контроллеров, чтобы маршруты выглядели как /admin/user/index, а файлы жили в отдельной папке.
Из чего состоит модуль
Минимальный работающий модуль — это один класс, унаследованный от yii\base\Module, и хотя бы один контроллер. Всё остальное (модели, представления, миграции) добавляется по мере надобности. Рекомендуемая структура каталогов для модуля admin внутри проекта на basic-шаблоне:
modules/
admin/
Module.php // класс модуля
controllers/
DefaultController.php
UserController.php
models/
User.php
views/
user/
index.php
create.php
assets/ // при необходимости
Ключевой момент — namespace. Yii находит контроллеры и представления по свойству controllerNamespace модуля, а классы грузит автозагрузчик Composer по PSR-4. Значит, физический путь и namespace должны совпадать. Если папка называется modules/admin, а в composer.json для приложения зарегистрирован псевдоним app\ на корень, то класс модуля получит namespace app\modules\admin.
Класс модуля
<?php
namespace app\modules\admin;
use yii\base\Module as BaseModule;
class Module extends BaseModule
{
// Namespace, в котором модуль ищет контроллеры.
// По умолчанию Yii подставит app\modules\admin\controllers,
// но лучше задать явно, чтобы поведение не зависело от версии.
public $controllerNamespace = 'app\\modules\\admin\\controllers';
public function init()
{
parent::init();
// Здесь можно переопределить компоненты модуля,
// подключить свою конфигурацию, задать layout.
$this->layout = 'main';
}
}
Свойство $id модуля задавать в классе не нужно — Yii присваивает его при регистрации по ключу в конфигурации.
Контроллер внутри модуля
<?php
namespace app\modules\admin\controllers;
use yii\web\Controller;
class UserController extends Controller
{
public function actionIndex()
{
// Ищет представление modules/admin/views/user/index.php
return $this->render('index');
}
}
Обратите внимание на namespace: ...\admin\controllers. Если вы положите контроллер в папку controllers, но оставите namespace без \controllers на конце, Yii класс не найдёт, потому что controllerNamespace указывает именно туда.
Как подключить модуль
Регистрация происходит в конфигурации приложения — для basic-шаблона это config/web.php, для advanced — common/config или frontend/config/main.php в зависимости от того, где нужен модуль. Модуль объявляется в массиве modules, а не components — это самая частая ошибка новичка.
return [
// ...
'modules' => [
'admin' => [
'class' => 'app\\modules\\admin\\Module',
// сюда можно передать параметры модуля
],
],
// ...
];
После этого маршрут строится по схеме идентификатор_модуля/контроллер/действие. Действие actionIndex контроллера UserController в модуле admin доступно по адресу index.php?r=admin/user/index, а при включённом ЧПУ — /admin/user/index.
Модуль — этоmodules, компонент приложения — этоcomponents. Перепутать легко, потому что синтаксис объявления одинаковый: ключ,class, параметры. Разница в том, что модуль даёт своё пространство маршрутов, а компонент — сервис, доступный черезYii::$app.
Bootstrap: когда модулю нужна инициализация на каждом запросе
Обычный модуль создаётся лениво — только когда пришёл маршрут внутрь него. Если модуль должен что-то делать при каждом запросе (регистрировать обработчики событий, добавлять URL-правила, инициализировать i18n), его метод bootstrap() нужно вызвать через секцию bootstrap конфигурации:
return [
'bootstrap' => ['admin'],
'modules' => [
'admin' => [
'class' => 'app\\modules\\admin\\Module',
],
],
];
Чтобы это сработало, класс модуля должен реализовать интерфейс yii\base\BootstrapInterface и метод bootstrap($app). Без этого добавление 'admin' в секцию bootstrap ничего не даст — init() вызовется, а bootstrap() нет.
<?php
namespace app\modules\admin;
use yii\base\Module as BaseModule;
use yii\base\BootstrapInterface;
class Module extends BaseModule implements BootstrapInterface
{
public $controllerNamespace = 'app\\modules\\admin\\controllers';
public function bootstrap($app)
{
// Например, добавляем свои URL-правила на каждом запросе
$app->getUrlManager()->addRules([
'admin' => 'admin/default/index',
], false);
}
}
Представления и вложенные модули
Представления модуля по умолчанию берутся из views/ внутри папки модуля, а не из общего views/ приложения. Layout модуля определяется свойством $layout: если оставить значение по умолчанию, Yii возьмёт layout приложения; задав $this->layout = 'main', вы укажете файл modules/admin/views/layouts/main.php.
Модули можно вкладывать друг в друга — тогда маршрут удлиняется: parent/child/controller/action. Вложенные модули регистрируются в свойстве modules уже родительского модуля, а не приложения. Это отдельная тема, здесь достаточно знать, что глубина ограничена только читаемостью маршрутов.
Если не получилось
- 404 Not Found на маршруте модуля. Проверьте, что модуль объявлен в
modules, а не вcomponents, и что ключ массива ('admin') совпадает с первым сегментом маршрута. - «Unable to find class: app\modules\admin\controllers\UserController». Namespace в файле контроллера не совпадает с
controllerNamespaceмодуля или с физическим путём. Убедитесь, что папка называетсяcontrollersи namespace оканчивается на\controllers. - «The view file does not exist». Файл представления лежит не в
views/user/index.phpвнутри модуля, а в общемviews/. Модуль ищет представления относительно своей папки. - bootstrap() не вызывается. Класс модуля не реализует
BootstrapInterface, либо идентификатор не добавлен в секциюbootstrapконфигурации. - «Class not found» после создания модуля вручную. Composer не знает о новом namespace. Если вы вышли за пределы уже зарегистрированного псевдонима
app\, добавьте маппинг вautoload.psr-4вcomposer.jsonи выполнитеcomposer dump-autoload.
Генерация модуля через Gii
Ручное создание файлов полезно для понимания, но в реальном проекте модуль удобнее сгенерировать. В Yii 2 генератор Gii умеет создавать заготовку модуля: класс Module.php, папки controllers, models, views и дефолтный контроллер. Достаточно указать ID модуля и целевой namespace — Gii сам расставит корректные namespace в файлах. После генерации модуль всё равно нужно вручную зарегистрировать в конфигурации, Gii этого не делает.
Что делать дальше
После того как модуль отвечает на маршруты, стоит настроить контроль доступа внутри него — общий фильтр AccessControl в init() модуля или в базовом контроллере модуля избавит от дублирования правил в каждом контроллере. Если модуль растёт до самостоятельного продукта, посмотрите в сторону вынесения его в отдельный Composer-пакет с собственным namespace — тогда подключение сведётся к require и одной строке в конфигурации. Точный синтаксис свойств Module и актуальный список методов сверяйте с документацией вашей версии Yii, приведённые примеры проверены на 2.0.49.
Создатель презентаций: Структура и текст каждого слайда: заголовки-утверждения, одна мысль на слайд, заметки докладчику.
Спросить за 150 ₽Источники: Yii 2.0 Guide — Modules, Yii 2 API — yii\base\Module
Частые вопросы
Чем модуль отличается от компонента в Yii 2?
Куда прописывать модуль в advanced-шаблоне?
У меня Yii другой версии, эти примеры сработают?
Почему после ручного создания модуля возникает Class not found?
Как заставить модуль выполнять код на каждом запросе?
Можно ли вкладывать один модуль в другой?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.