Search code examples
yii2yii2-module

Yii2 Module with different database


I want to combine two applications. One of these as module. There are two different databases. The Module use another database as the base appliaction.

I have created the db connection, which is a component in config.php

return [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=test_db',
    'username' => 'root',
    'password' => '',    
    'charset' => 'utf8',
];

And I have created an ModuleActiveRecord Class which overwrites the Active Record function getDB():

class ModuleActiveRecord extends ActiveRecord
{
    public static function getDb()
    {
        $db = Yii::$app->controller->module->db;
        return Yii::createComponent($db);
}

I get the error message: The table does not exist. Anyone an idea??


Solution

  • You can add multiple database connections like the other answers, for example: db/db_for_module.

    You can also configure the module like I do(Example using Yii2 advanced template):

    // in common/config/main.php
    [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=test_db',
            'username' => 'root',
            'password' => '123456',    
            'charset' => 'utf8',
        ],
        'modules' => [
            'v1' => [
                'class' => \frontend\modules\v1\Module::class,
                // Increase the component configuration of the module
                'components' => [
                    'db' => [
                        'class' => 'yii\db\Connection',
                        'dsn' => 'mysql:host=localhost;dbname=test_db_for_module',
                        'username' => 'root',
                        'password' => '111111',    
                        'charset' => 'utf8',
                    ],
                ],
            ],
        ],
    ]
    

    Definition of v1 module

    // in frontend/modules/Module.php
    <?php
    
    namespace frontend\modules\v1;
    
    /**
     * v1 module definition class.
     */
    class Module extends \yii\base\Module
    {
        /**
         * {@inheritdoc}
         */
        public $controllerNamespace = 'frontend\modules\v1\controllers';
    }
    

    However, you have to call the db component in a special way in the module's code, for example:

    // in frontend/modules/v1/controllers/TestController.php
    <?php
    
    namespace frontend\modules\v1\controllers;
    
    /**
     * Test Controller
     */
    class TestController extends \yii\web\Controller {
    
        public function actionTest()
        {
            \Yii::$app->modules['v1']->db->createCommand(...); // This db points to the db connection of this module configuration
            // or
            $this->module->db->createCommand(...) // This db points to the db connection of this module configuration
        }
    }
    

    The benefits of doing this:

    • You can use the same name: db (if this is what you expect, although it's called in a special way)
    • The code other than this module can't see the configuration about this db.
    • Even if you don't have a special db connection for this module, you can still call the default db connection correctly using the above method (maybe this is not what you expect)
    • Can clearly indicate that a special db connection configuration is used here

    Note: This is just a way to override the application default components in the module for reference. I have not practiced this method, but I have tested this is feasible.