= 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'': 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: [ '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: [ '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: getModule('requisition'); $isModuleInstalled = !empty($module); ?> 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 == getModule('erp'); $isModuleInstalled = !empty($module); ?> 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 ); // });' //]); ?> field($model, 'item_code')->textInput(['maxlength' => true]) ?> 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) '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'' '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: '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) // NOTE: To query the raw table name, use the following: // echo Yii::$app->db->schema->getRawTableName(app\models\ItemProduct::tableName()); // Displays as follows (assuming 'mod_' table prefix): // mod_item_product } /** * 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-label"); // use private database for module 'label' } //... } == References == * [[http://www.yiiframework.com/doc-2.0/guide-structure-modules.html|Yii 2 Guide: Creating Modules]] * [[https://stackoverflow.com/questions/27254540/multiple-database-connections-and-yii-2-0|Multiple Database Connections in Yii 2]] * [[https://stackoverflow.com/questions/34051383/yii2-modules-in-advanced-template|Yii 2 Modules in Advanced template]] * [[https://www.yiiframework.com/doc/guide/2.0/en/concept-autoloading|Yii 2 Class Autoloading and Namespaces]] * [[https://www.yiiframework.com/doc/guide/1.1/en/basics.namespace|Yii 1.1 Namespaces]] * [[https://github.com/yiisoft/yii2/issues/3647|Better configuration of frontend, backend, and modules]] * [[https://yii2-cookbook.readthedocs.io/structure-backend-frontend-modules/|Yii 2 Cookbook: Structure of Backend/Frontend Modules]]