Search code examples
yii

Yii: override getDbConnection method and set CDbConnection from the master db to a slave db


For some reason I cant switch the db connection to save data in the secondary dbs.

db tables from the main db:

I have a website model class that stores data about a website.

WebsiteM extends Website wich extends CActiveRecord

I have a url model class that stores data about a url.

UrlM extends Url wich extends CActiveRecord

Each url belongs to a website; each url has a FK named website_id that tells the website that it belongs to;

Because the website model and url model are changing daily, I wrote for each model a new class that extends them, like websiteM extends website and urlM extends url and this way when I regenerate the models using gii, my enhancements are always saved.

db table from the slave db:

I have a slave url model class that stores data about a url in one of the slave active dbs.

The slave url model is the same as the main url model;

It's like this: UrlSlaveM extends UrlSlave wich extends HActiveRecord wich extends CActiveRecord

At some point, I try to switch to a secondary db, by using relations to find out the id of the db that I need to switch to, after new class instance like:

$model_urlSlave_new = new UrlSlaveM();

$model_urlSlave_new::$server_id = $model_url->websiteM_relation->database_id;

This should work, but it does not. This is where the action happens, this is where the connection should switch:

class HActiveRecord extends CActiveRecord {

    public static $server_id = 2;
    public static $master_db;

    public function getDbConnection() {
        self::$master_db = Yii::app()->{"db" . self::$server_id};
        if (self::$master_db instanceof CDbConnection) {
            self::$master_db->setActive(true);
            return self::$master_db;
        }
        else
            throw new CDbException(Yii::t('yii', 'Active Record requires a "db" CDbConnection application component.'));
    }

}

settings in main.php

'db' => array(
            'connectionString' => 'mysql:host=localhost;dbname=dvc',
            'emulatePrepare' => true,
            'username' => 'root',
            'password' => '',
            'charset' => 'utf8',
        ),
        'db2' => array(
            'connectionString' => 'mysql:host=localhost;dbname=dvc2',
            'username' => 'root',
            'password' => '',
            'charset' => 'utf8',
            'tablePrefix' => '',
            'class' => 'CDbConnection'          // DO NOT FORGET THIS!
        ),
        'db1' => array(
            'connectionString' => 'mysql:host=localhost;dbname=dvc1',
            'username' => 'root',
            'password' => '',
            'charset' => 'utf8',
            'tablePrefix' => '',
            'class' => 'CDbConnection'          // DO NOT FORGET THIS!
        ),

Solution

  • I found the solution:

    The following code was moved to the main model class and the hactiverecord class was deleted.

    public static $server_id = 2;
        public static $master_db;
    
        public function getDbConnection() {
            self::$master_db = Yii::app()->{"db" . self::$server_id};
            if (self::$master_db instanceof CDbConnection) {
                self::$master_db->setActive(true);
                return self::$master_db;
            }
            else
                throw new CDbException(Yii::t('yii', 'Active Record requires a "db" CDbConnection application component.'));
        }
    

    it works. tested.