工作遇到了分库的问题,所谓分库,不是单指是用多个数据库,而是将单个数据库拆分成多个逻辑功能平行的库(通俗的举例说就是讲一个数据库拷贝多份,然后分给每个公司客户一个,它们各自用自己的)。废话不多说,下面介绍使用方法,此为本人原创,笔者架构水平经验有限,仅供参考。
一.首先,需要了解Yii2使用多个数据库的方法
1.在配置文件中(建议main-local.php)中加上数据库配置:
'components' => [
//单库
'db1' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=127.0.0.1;dbname=dbname1',
'username' => '****',
'password' => '****',
'charset' => 'utf8',
'tablePrefix' => 'tpr_',
],
//单库
'db2' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=127.0.0.1;dbname=dbname2',
'username' => '****',
'password' => '****',
'charset' => 'utf8',
'tablePrefix' => 'tpr_',
],
]
2.直接使用的方法:
$Db = \Yii::$app->db1;
$res1 = $Db->createCommand('SELECT * FROM user limit 1')->queryOne();
$Query = new \yii\db\Query();
$res2 = $Query->where(array('id'=>1))->from('user')->limit(1)->one($Db);
3.使用模型,首先在models目录下建立User.php,示例目录是\common\models\dbname1\:
db1;
}
}
使用方法:
$User = new \common\models\core\User();
$res1 = $User::find()->where(array('id'=>1))->limit(1)->asArray()->one();
$Query = new \yii\db\Query();
$res2 = $Query->where(array('id'=>1))->from($User::tableName())->limit(1)->one($User::getDb());
二.在使用多个库的情况下再进行分库
1.首先将配置中的class改为自定义的class,示例的类文件为\common\components\db\MysqlConnection.php:
'components' => [
//分库
'db1' => [
'class' => 'common\components\db\MysqlConnection',
'dbname' => 'dbname1',
'charset' => 'utf8',
'tablePrefix' => 'tpr_',
],
//分库
'db2' => [
'class' => 'common\components\db\MysqlConnection',
'dbname' => 'dbname2',
'charset' => 'utf8',
'tablePrefix' => 'tpr_',
],
]
2.编写MysqlConnection类:
直接使用的方法:
//使用初始化的连接
$Db1 = \Yii::$app->db1;
//自定义参数的连接,会覆盖配置文件中的参数
$config = array(
//分库的配置参数,此处的处理逻辑及参数规则需要自己在MysqlConnection.php里编写,这里只给个思路
'db' => 'db2', //使用db2的配置参数
'fk_config' => array(
'val1' => '****',
'val3' => '****',
'val3' => '****',
)
);
$Db2 = new \common\components\db\MysqlConnection($config);
3.在模型中使用,先修改模型文件User.php
namespace common\models\dbname1;
use yii\db\ActiveRecord;
class User extends ActiveRecord{
protected static $myconfig;
function __construct($config = array()){
if($config){ //如果有自定义参数
self::$myconfig['fk_config'] = $config;
}
parent::__construct();
}
public static function getDb(){
if(self::$myconfig){ //处理自定义参数
self::$myconfig['db'] = 'db1';
return new \common\components\db\MysqlConnection(self::$myconfig);
}else{
return \Yii::$app->db_core;
}
}
}
使用方法:
//使用初始化的参数
$User = new \common\models\dbname1\User();
//自定义参数的模型,会覆盖配置文件中的参数
$fk_config = array(
//分库的配置参数,此处的处理逻辑及参数规则需要自己在MysqlConnection.php里编写,这里只给个思路
'val1' => '****',
'val3' => '****',
'val3' => '****',
);
$User = new \common\models\dbname1\User($fk_config);
其实每个数据表模型中都要写__construct()和getDb()是不太合理的,可以写个通用模型作为父类写入__construct()和getDb(),然后数据表模型继承此模型即可,笔者就是这么做的但没有写出来,因为写出来会增加阅读和理解难度,读者可以自己去尝试。