This is an old revision of the document!
Yii 2 Modules
Create Module Manually
- Create a
modules
folder on the application base path. This matches the@app
alias of the current application. Same procedure for basic or advanced application (backend/frontend). Eg:app/modules
- Create a folder for your module corresponding to the Module ID. Eg:
app/modules/product
- Create the Module Class (eg
Module
) inside this module folder (eg.app/modules/product/Module.php
). The custom module definition must extend\yii\base\Module
.
Eg.: For product module class, create file app/modules/product/Module.php
:
<?php namespace app\modules\product; class Module extends \yii\base\Module { public $controllerNamespace = 'app\modules\product\controllers'; public function init() { parent::init(); // custom initialization code goes here } }
Create the module controllers
, models
and views
subfolders on the module folder. Eg:
app\modules\Product\controllers
app\modules\Product\models
app\modules\Product\views
To make the module accessible, add references in the application configuration:
<?php //...... 'modules' => [ 'product' => [ 'class' => 'app\modules\product\Module', 'components' => [ 'db' => [ 'tablePrefix' => 'module_', // override main 'db' component attributes ], ], ], ], //......
Create Module Automatically (Gii)
- Using Gii module, go to the module generator and enter path to module class. Eg:
app\modules\product\Module
- Preview and Generate all files.
- To make the module accessible, add references in the application configuration:
<?php //...... 'modules' => [ 'product' => [ 'class' => 'app\modules\product\Module', 'components' => [ // Main application database 'db' => [ 'class' => 'yii\db\Connection', ], // Custom module database //'db-mod-product' => [ // 'class' => 'yii\db\Connection', // 'dsn' => 'mysql:host=localhost;dbname=acme_product', // 'username' => 'dbuser', // 'password' => 'secret', // 'charset' => 'utf8', // 'tablePrefix' => 'mod_', //], ], ], ], //......
Module Detection or References
To detect (in a view) whether a particular module is installed:
<?php // detect installation of child module whose ID is "requisition" $module = \Yii::$app->getModule('requisition'); $isModuleInstalled = !empty($module); ?> <?php if ($isModuleInstalled): ?> <a class="btn btn-lg btn-default" href="<?= Url::to(['requisition/custom-order/index']); ?>"> <i class="fa fa-cart-plus" aria-hidden="true"></i> Requisition </a> <?php endif; ?> <?php // Alternatively $isModuleInstalled = yii\base\Module::has('requisition'); ?>
To get a module reference (eg: module “forum”):
// get module reference $module = \app\modules\forum\Module::getInstance(); // Format: MyModuleClass::getInstance(); // get the child module whose ID is "forum" (when you know the module name) $module = \Yii::$app->getModule('forum'); // get the module to which the currently requested controller belongs // (when you know the controller, but not the module name) $module = \Yii::$app->controller->module; // or... $module = $this->module; // not tested yet
Target | Variable | Description |
---|---|---|
module name | Yii::$app→controller→module→id | |
module name | $this→module→id |
To reference a model in the module (eg: model “Posts” in module “forum”):
$models = \app\modules\forum\models\Posts::find()->all();
To reference the module url (eg: view “index” of model “Posts” in module “forum”):
http://localhost:8080/[myapp]/web/forum/posts/index
Example View
<?php // detect installation of child module whose ID is "erp" $module = \Yii::$app->getModule('erp'); $isModuleInstalled = !empty($module); ?> <?php if ($isModuleInstalled): ?> <?= /* ### METHOD 1 ### */ $form->field($model, 'item_code') ->textInput([ 'maxlength' => true, 'onchange' => '$.get( "'.Yii::$app->homeUrl.'/erp/inventory/getdescription?item_code="+$(this).val(), function( data ) { $( "#proformaitem-description1" ).val( data ); });' ]); /* ### METHOD 2: This lookup solution is too slow ### */ //$form->field($model, 'item_code')->dropDownList( //yii\helpers\ArrayHelper::map(\app\modules\erp\models\Inventory::find()->all(), 'item_code', 'description1'), //[ // //'prompt' => '--Select One--', // 'onchange' => '$.get( "'.Yii::$app->homeUrl.'/erp/inventory/getdescription?item_code="+$(this).val(), function( data ) { // $( "#proformaitem-description1" ).val( data ); // });' //]); ?> <?php else: ?> <?= $form->field($model, 'item_code')->textInput(['maxlength' => true]) ?> <?php endif; ?> <?= $form->field($model, 'description1')->textInput(['maxlength' => true]) ?>
Using Custom Database
Sometimes your module needs to use a separate custom database. You can do so in Yii by adding a new db
section in its configuration, and pointing the module models to new private database.
Steps: Add a new database file configuration (or new db
array in config). Eg: file @app/config/db-mod-label.php
(in addition to the app's db.php
file)
<?php return [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=acme_labels', 'username' => 'dbuser', 'password' => 'secret', 'charset' => 'utf8', //'tablePrefix' => 'main_', ];
Add a reference to this file in the app config section. Eg: @app/config/web.php
<?php $params = require(__DIR__ . '/params.php'); $config = [ 'id' => 'basic', //... 'components' => [ //... 'db' => require(__DIR__ . '/db.php'), 'db-mod-label' => require(__DIR__ . '/db-mod-label.php'), // custom database for module //... ], 'params' => $params, ]; //...
Alternatively:
application configuration: <code php> <?php //... $config = [ 'id' => 'basic', //... 'components' => [ //... 'db' => require(__DIR__ . '/db.php'), //... ], 'modules' => [ 'label' => [ 'class' => 'app\modules\label\Module', 'components' => [ // Option 1: custom database for module // // In @app/config/db-mod-label.php: //'db-mod-label' => require(__DIR__ . '/db-mod-label.php'), // // In @app/modules/label/config/db-mod-label.php: //'db-mod-label' => require(__DIR__ . // DIRECTORY_SEPARATOR . '..' . // DIRECTORY_SEPARATOR . 'modules' . // DIRECTORY_SEPARATOR . 'printlog' . // DIRECTORY_SEPARATOR . 'config' . // DIRECTORY_SEPARATOR . 'db-mod-printlog.php' //), // Option 2: custom database for module 'db-mod-label' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=acme_labels', 'username' => 'dbuser', 'password' => 'secret', 'charset' => 'utf8', 'tablePrefix' => 'mod_', ], ], ], ], 'params' => $params, ]; //...
Now, in each model found in the module, override the function getDb()
to connect to this custom database:
//... class ItemProduct extends \yii\db\ActiveRecord { /** * @inheritdoc */ public static function tableName() { return "{{%item_product}}"; // formatted to allow table prefix (where % goes) } /** * Override parent getDb() so we can connect to private module database. */ public static function getDb() { // Get custom connection from app. //return Yii::$app->get('db'); // use main application database // Get custom connection from module (preferable). // In Yii 2.0.13 and newer, it is preferable to use $module->get('db') // instead of getting a connection from app (using Yii::$app->get('db')) $module = \Yii::$app->controller->module; return $module->get("db-mod-{$module->id}"); // use private module database } //... }