Switch Beetween Two Db (Read - Read/write)

I have 2 database as A which is ReadOnly and B which is Read/Write,

now how can i handle it in all of my Models?

Dear Friend

I am not fully able to comprehend your requirement.

I hope that you need one database for index and view actions;

another one for create,update and admin actions.

In main configuration file ,if you have set database A as your main db component,

Then in controller.php in components folder, we can override the beforeAction method.




class Controller extends CController

{

..............

..............


protected function beforeAction($action)

	{   if($action->id=="update" || $action->id=="create" || $action->id=="admin")

	       {

		    Yii::app()->db->setActive(false);

		    Yii::app()->setComponent('db',new CDbConnection('mysql:host=localhost;dbname=B',

			        'root','yourPassword'

			      ));//connectionstring,username,password

	            Yii::app()->db->setActive(true);

		}

	     return true;

	}



Thus actions index and view uses database A.

Actions create,update and admin uses database B.

Table structure for a particular Model should remain same in both databases.

Regards.

Thanks for you help, but now i have hundreds of action, for that what is the solution?

my requirements is something like this extension,

http://www.yiiframework.com/extension/dbreadwritesplitting

Dear Friend

Now we can forget about overiding the before action method.

We can overide the init method of CController.

Components/Controller.php




.....................................

.....................................

public function init()

{   if(Yii::app()->user->id==1) //admin. here you can put whatever condition you want....

         {

                 Yii::app()->db->setActive(false);

                 Yii::app()->setComponent('db',new CDbConnection('mysql:host=localhost;dbname=B',

                                'root','yourPassword'

                              ));//connectionstring,username,password

                 Yii::app()->db->setActive(true);

          }

}



Regards

You should not even do this on a controller level, this should be done on Model level.

Every ActiveRecord has a "getDbConnection()" function that usually just returns the "db" component.

This is used by Yii for everything (both finds and updates)

What I did was make my own CActiveRecord derived class where my getDbConnection function returns a property (‘oCurrentConnection’). By default this points to my read-only DB.

Then you override all data modifying functions like insert, update, delete and so on to set the connection to use to the write one, call the parent function and then put it back on the read one.

So for example the update function would go like:


public function update($aAttributes = NULL)

{

  $this->oCurrentConnection = Yii::app()->dbWrite;

  $result = parent::update($aAttributes);

  $this->oCurrentConnection = Yii::app()->db;

  return $result;

}



So during the call your getDbConnection function returns a handle to the write-connection and the rest of the time this would be the read connection.

If you do it like this then all you have to do is change the base class for your models from CActiveRecord to CMyActiveRecord (or however you call it).

This is just an oversimplified way of doing it (i have a generic callParent function that does this for me so I don’t have to write the same code over and over), but this is how you would do it.

Dear Blizz

Things are looking elegant when done at model level.

Many thanks for sharing the information.

Regards.