What would you do if you want/need to have a different than the main database connection in an module's models?
How to use ¶
Let's say we create a module with name test under the protected/modules/
folder.
Configuration ¶
In your config file you can declare a module like:
'modules'=>array(••••••
'test'=>array(
'db'=>array(
'class'=>'CDbConnection',
'connectionString'=>'sqlite:'.dirname(__FILE__).'/../modules/bliig/data/blog.db',
),
),
Important: The 'class'=>'CDbConnection'
is required, for this simple implementation.
CModule ¶
In your TestModule.php
file ( the class that extends the CModule
) under the protected/modules/test
folder, declare a public property named db.
class TestModule extends CModule
{
public $db;
...
}
Your models ¶
Then you have to simple change the CActiveRecord
class your module's models extends to EModuleActiveRecord
class EModuleActiveRecord extends CActiveRecord
{
public function getDbConnection()
{
$db = Yii::app()->controller->module->db;
return Yii::createComponent($db);
}
}
Notes ¶
In this scenario we had a module that we wanted to change database for, but the extension of the CActiveRecord
and the
override of the getDdConnection()
is common general a common case.
Make sure you import the EModuleActiveRecord
. If you have generated the module with gii, just add file under the
components or models folder.
Great post
Thanks a lot.
It was very usefull for me.
Roberto
Too many connections
Great entry, although I've been getting the following SQL error:
yii CDbConnection failed to open the DB connection: SQLSTATE[08004] [1040] Too many connections
In my module I have a page that requires a lot of queries to be run (fetching a lot of unrelated models from the db) and I was getting an SQL too many connections error. I think, although I may be wrong, that this is because the system was opening a new database connection for every model I loaded.
Rather than increasing the 'max connections' value for the MySQL server, I found another way around. Instead of adding the db connection as as param of the module, I added it as a db connection in the main site configuration, next to the original database connection;
'db'=>array( 'connectionString'=>'mysql:host=localhost;dbname=my_db_name', 'username'=>'my_db_username', 'password'=>'my_db_password', .... ), 'moduleDb'=>array( 'connectionString'=>'mysql:host='.$connectionString.';dbname=my_module_db_name', 'username'=>'my_module_db_username', 'password'=>'my_module_db_password', 'class'=>'CDbConnection', .... ),
Adding the
$db
property to my module file, and also extending all models within the module fromEModuleActiveRecord
, as you have stated. However I've edited thegetDbConnection()
method withinEModuleActiveRecord
like so:public function getDbConnection() { return Yii::app()->moduleDb; }
This sets the DB connection to the global application moduleDb, and doesn't create a new connection with every model.
A better alternative
I first used your class and worked great. However, I had problems because I wanted to use auth manager in modules and I got errors. Here I show the solution if we want to use a database in modules along with auth manager:
public function init() { $this->setImport(array( 'blog.models.*', 'blog.components.*', )); Yii::app()->setComponents( array( 'db'=>array( 'class'=>'CDbConnection', 'tablePrefix' => 'tbl_', 'connectionString'=>'sqlite:' .dirname(__FILE__) . '/data/blog.sqlite', ), 'authManager'=>array( 'class'=>'CDbAuthManager', 'connectionID'=>'db', 'itemTable'=>'tbl_auth_item', 'itemChildTable'=>'tbl_auth_item_child', 'assignmentTable'=>'tbl_auth_assignment', ) ); } }
Great entry, although I've been getting the following SQL error:
yii CDbConnection failed to open the DB connection: SQLSTATE[08004] [1040] Too many connections
In my module I have a page that requires a lot of queries to be run (fetching a lot of unrelated models from the db) and I was getting an SQL too many connections error. I think, although I may be wrong, that this is because the system was opening a new database connection for every model I loaded.
Rather than increasing the 'max connections' value for the MySQL server, I found another way around. Instead of adding the db connection as as param of the module, I added it as a db connection in the main site configuration, next to the original database connection;
'db'=>array( 'connectionString'=>'mysql:host=localhost;dbname=my_db_name', 'username'=>'my_db_username', 'password'=>'my_db_password', .... ), 'moduleDb'=>array( 'connectionString'=>'mysql:host='.$connectionString.';dbname=my_module_db_name', 'username'=>'my_module_db_username', 'password'=>'my_module_db_password', 'class'=>'CDbConnection', .... ),
Adding the $db property to my module file, and also extending all models within the module from EModuleActiveRecord, as you have stated. However I've edited the getDbConnection() method within EModuleActiveRecord like so:
public function getDbConnection() { return Yii::app()->moduleDb; }
This sets the DB connection to the global application moduleDb, and doesn't create a new connection with every model.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.