In this paper, we analyze the method to realize MySQL multiple database and read-write separation by Yii. Share to everyone for your reference. The specific analysis is as follows:
The YII framework is a high-performance PHP framework for developing large Web applications based on components. Yii provides almost everything that today's Web 2.0 application development needs and is one of the most powerful frameworks, and here's how to implement the MySQL multi-Library and read-write separation of Yii
Some time ago for SNS products made the architectural design, in the framework of the program has done a lot of related stress testing, the final selection of yiiframework, as for why not the company's internal PHP framework, in fact, the reason is very full, although the company's framework is "predecessors" of the hard accumulation, but not mature enough, Without the experience of a large project, it is like a young boy who is inexperienced. Yii as a well-known open source product, there must be a lot of people in the use, means that there are a number of people in the maintenance, and before that, I also used yii to develop large projects, Yii's design pattern and its easy to expand features enough to worthy the task.
SNS and the general social product is the difference is it eventually to bear the test of large concurrency and large data, architecture design to consider these issues, Web distributed, load balancing, Distributed file storage, MySQL distributed or read and write separation, NoSQL and a variety of caching, these are essential applications, This article is about MySQL library and master-slave read-write separation in Yii configuration and use.
Yii By default does not support read-write separation, we can use Yii event-driven mode to achieve MySQL read and write separation.
Yii provides a powerful Cactiverecord database operation class, by rewriting the Getdbconnection method to implement database switching, and then through event BeforeSave, BeforeDelete, Beforefind To achieve the switching of read and write server, also need two profiles dbconfig and Modelconfig respectively Configure the database master server and model corresponding to the database name, with code
dbconfig.php files are as follows:
Copy Code code as follows:
<?php
Return Array (
' Passport ' => array (
' Write ' => array (
' Class ' => ' cdbconnection ',
' connectionString ' => ' mysql:host=10.1.39.2;dbname=db1′,
' Emulateprepare ' => true,
' Enableparamlogging ' => true,
' Enableprofiling ' => true,
' username ' => ' root ',
' Password ' => ',
' CharSet ' => ' utf8′,
' Schemacachingduration ' =>3600,
),
' Read ' => array (
Array
' Class ' => ' cdbconnection ',
' connectionString ' => ' mysql:host=10.1.39.3;dbname=db1,
' Emulateprepare ' => true,
' Enableparamlogging ' => true,
' Enableprofiling ' => true,
' username ' => ' root ',
' Password ' => ',
' CharSet ' => ' utf8′,
' Schemacachingduration ' =>3600,
),
Array
' Class ' => ' cdbconnection ',
' connectionString ' => ' mysql:host=10.1.39.4;dbname=db3′,
' Emulateprepare ' => true,
' Enableparamlogging ' => true,
' Enableprofiling ' => true,
' username ' => ' root ',
' Password ' => ',
' CharSet ' => ' utf8′,
' Schemacachingduration ' =>3600,
),
),
),
);
Modelconfig.php is as follows:
Copy Code code as follows:
<?php
Return Array (
Key is the database name, value is model
' Passport ' => array (' User ', ' Post '),
' Microblog ' => array (' ... '),
);
?>
Activerecord.php is as follows:
Copy Code code as follows:
/**
* Based on the encapsulation of Cactiverecord class, realize the separation of multi-Library and master-slave reading
* All model must inherit some classes.
*
*/
Class ActiveRecord extends Cactiverecord
{
Model configuration
Public $modelConfig = ';
Database configuration
Public $dbConfig = ';
Define a multiple database collection
Static $dataBase = Array ();
Current database name
Public $dbName = ';
Define library type (read or write)
Public $dbType = ' read '; ' Read ' or ' write '
/**
* Added a dbname parameter on the original basis
* @param the application scenario for string $scenario model
* @param string $dbname database name
*/
Public function __construct ($scenario = ' Insert ', $dbname = ')
{
if (!empty ($dbname))
$this->dbname = $dbname;
Parent::__construct ($scenario);
}
/**
* Overriding the Getdbconnection method of the parent class
* Multi-Library and master-slave are here to switch
*/
Public Function getdbconnection ()
{
Returns directly if the specified database object exists
if (self:: $dataBase [$this->dbname]!==null)
Return self:: $dataBase [$this->dbname];
if ($this->dbname = = ' db ') {
Self:: $dataBase [$this->dbname] = Yii::app ()->getdb ();
}else{
$this->changeconn ($this->dbtype);
}
if (self:: $dataBase [$this->dbname] instanceof cdbconnection) {
Self:: $dataBase [$this->dbname]->setactive (TRUE);
Return self:: $dataBase [$this->dbname];
} else
throw new CDBException (Yii::t (' Yii ', ' Model requires a "DB" Cdbconnection application.));
}
/**
* Get configuration file
* @param unknown_type $type
* @param unknown_type $key
*/
Private Function GetConfig ($type = "Modelconfig", $key = ") {
$config = Yii::app ()->params[$type];
if ($key)
$config = $config [$key];
return $config;
}
/**
* Get the database name
*/
Private Function Getdbname () {
if ($this->dbname)
return $this->dbname;
$modelName = Get_class ($this->model ());
$this->modelconfig = $this->getconfig (' modelconfig ');
Get the database name of model
if ($this->modelconfig) foreach ($this->modelconfig as $key => $val) {
if (In_array ($modelName, $val)) {
$dbName = $key;
Break
}
}
return $dbName;
}
/**
* Switch Database connection
* @param unknown_type $dbtype
*/
protected function changeconn ($dbtype = ' read ') {
if ($this->dbtype = = $dbtype && self:: $dataBase [$this->dbname]!== null)
Return self:: $dataBase [$this->dbname];
$this->dbname = $this->getdbname ();
if (Yii::app ()->getcomponent ($this->dbname. ') _ '. $dbtype)!== null) {
Self:: $dataBase [$this->dbname] = Yii::app ()->getcomponent ($this->dbname. ') _ '. $dbtype);
Return self:: $dataBase [$this->dbname];
}
$this->dbconfig = $this->getconfig (' Dbconfig ', $this->dbname);
According to the type of the corresponding configuration (from the library is a random value)
if ($dbtype = = ' Write ') {
$config = $this->dbconfig[$dbtype];
}else{
$slavekey = Array_rand ($this->dbconfig[$dbtype]);
$config = $this->dbconfig[$dbtype] [$slavekey];
}
To add a database configuration to component
if ($dbComponent = Yii::createcomponent ($config)) {
Yii::app ()->setcomponent ($this->dbname. ') _ '. $dbtype, $dbComponent);
Self:: $dataBase [$this->dbname] = Yii::app ()->getcomponent ($this->dbname. ') _ '. $dbtype);
$this->dbtype = $dbtype;
Return self:: $dataBase [$this->dbname];
} else
throw new CDBException (Yii::t (' Yii ', ' Model requires a "changeconn" cdbconnection application component. '));
}
/**
* Select Primary database before saving data
*/
protected function BeforeSave () {
Parent::beforesave ();
$this->changeconn (' write ');
return true;
}
/**
* Select Primary database before deleting data
*/
protected function BeforeDelete () {
Parent::beforedelete ();
$this->changeconn (' write ');
return true;
}
/**
* Read data selection from database
*/
protected function Beforefind () {
Parent::beforefind ();
$this->changeconn (' read ');
return true;
}
/**
* Get Master Library object
*/
Public Function Dbwrite () {
return $this->changeconn (' write ');
}
/**
* Get Slave Library objects
*/
Public Function DBRead () {
return $this->changeconn (' read ');
}
}
This is my written class, put in the Components folder, and then all the model inherits ActiveRecord class can realize multiple library and master-slave read and write separation, as to how to support native SQL also use read-write separation, this class has been implemented.
I hope this article will help you with the PHP program design based on the YII framework.