如果存在主从数据库或者是数据库组,需要经常切换操作,不知道有什么好的操作方法没有?
从其它版块搜索好像有答案是自己修改CActiveRecord的getDbConnection方法,不知道有没有其它的方法啊?
如果存在主从数据库或者是数据库组,需要经常切换操作,不知道有什么好的操作方法没有?
从其它版块搜索好像有答案是自己修改CActiveRecord的getDbConnection方法,不知道有没有其它的方法啊?
你可以在配置文件里声明多个数据库连接,然后通过Yii::app()->db1, Yii::app()->db2…来访问它们。更高级(自动)的主从数据库功能将在1.1实现。
正琢磨这个事呢。刚巧Fyzeng问了。谢谢强。
对于AR内部的调用流程看了半天,也没看太明白,不得不再请教一次。
以文档里的实例来说,现在用脚手架生成了user的model。在Controller里实例化后默认操作的就是配置文件里的db配置。如果我现在多加一个配置(如:db2),在UserController里如何可以使这个db2生效呢?
我的想法是:
父类CActiveRecord给一个方法(或一个public的变量),可以通过这个切换来决定getDbConnection返回哪个配置的链接
model方法多给一个同样性质的参数来决定采用哪个数据库配置
我想尝试做来着,但水平有限,看了半了源码,也没找着getDbConnection在哪调用的,汗颜中……
方法1: 重写getDbConnection(),返回你想要的DB连接。
方法2: 设置CActiveRecord::$db
大多数情况下,我们都会采用同一类型的数据库,只是为了缓解压力分成主从或分布式形式而矣。重新看了遍代码,实在认为没有必要改getDbConnection()这个方法,因为只变数据库ip, 操作类我还是很希望用AR的,因为实在很喜欢脚手架的功能,它生成的Model就是继承的AR类。现在我的做法是简单的改了base里的两个方法,在不影响原功能的情况下,多加了一个参数,这样问题是解决了,但总觉得别扭,因为修改了base里的方法,以后升级Yii会是个麻烦事。望有兴趣朋友一起讨论下。
我的具体做法如下:
修改了/framework/CModule.php(313)
public function getComponent($id,$configKey=null) { $configKey = ($configKey===null) ? $id : $configKey; if(isset($this->_components[$configKey])) return $this->_components[$configKey]; else if(isset($this->_componentConfig[$configKey])) { $config=$this->_componentConfig[$configKey]; unset($this->_componentConfig[$configKey]); if(!isset($config['enabled']) || $config['enabled']) { Yii::trace("Loading "$id" application component",'system.web.CModule'); unset($config['enabled']); $component=Yii::createComponent($config); $component->init(); return $this->_components[$configKey]=$component; } } }
/framework/CApplication.php(336) 也做了相应的修改
public function getDb($configKey=null) { return $this->getComponent('db',$configKey); }
这样调用的时候就可以在实际操作之前通过如下操作形式自由切换了
//以user表建立好了model为例 用户列表的片断如下 $criteria=new CDbCriteria; user::$db = Yii::app()->getDb('db2');//这里的db2可以是main.php的配置的任意数据库参数 $userList=user::model()->findAll($criteria);
建议不要直接改核心代码。
同样的功能现在已经支持。你可以在app config里声明其它的数据库连接:
<?php 'components'=>array( 'db'=>....// 主链接 'db1'=>...// 从连接1 'db2'=>...// 从连接2 )
在代码里,可以通过Yii::app()->db1和Yii::app()->db2获得两个从连接。
谢谢qiang, 这下终于搞明白该怎么弄了。
顶你,加油,期待强大的新版本!
‘db’=>array(
'connectionString'=>'mysql:host=localhost;dbname=test',
'charset'=>'utf8',
'username'=>'root',
'password'=>'root',
),
‘db2’=>array(
'connectionString'=>'mysql:host=localhost;dbname=test',
'charset'=>'utf8',
'username'=>'root',
'password'=>'root',
),
$conn = Yii::app()->db2;
$command = $conn->createCommand($sql);
$command->execute();
return false;
Object configuration must be an array containing a "class" element.
是这么使用么?
It’s ok now.
‘db’=>array(
'class' => 'CDbConnection',
)
学习~~~
主链接key必须是“db”吗?
如果我有两个DB,分别叫A, B,我希望可以直接Yii::app()->A 或者 Yii::app()->B, 如下配置就可以:
‘components’=>array(
‘db’=>…// 主链接,必须的
‘A’=>...// DB A
‘B’=>...// DB B
)
但是如下这样就报错: CDbConnection.connectionString cannot be empty.
‘components’=>array(
‘A’=>...// DB A
‘B’=>...// DB B
)
尽管可以实现,但是必须要配置一个叫“db”的链接,感觉很别扭。
在 config 里面 components 添加:
A=>array('class'=>'CDbConnection','connectionString'=>'...')
注意,要配置’class’=>‘CDbConnection’
使用的时候,用 SomeARClass::$db=Yii::app()->A
不要用Yii::app()->getDb(‘A’);
Yii source: CApplication.php
public function getDb()
{
return $this->getComponent('db');
}
是直接指到’db’的
或者extends CActiveRecord重写getDbConnection()方法,这样更方便
class MultiDbActiveRecord extends CActiveRecord
{
protected $dbString='db';
public function getDbConnection()
{
if(self::$db!==null)
return self::$db;
else
{
$dbString=$this->dbString;
self::$db=Yii::app()->$dbString;
if(self::$db instanceof CDbConnection)
{
self::$db->setActive(true);
return self::$db;
}
else
throw new CDbException(Yii::t('yii','...'));
}
}
}
这样直接在AR class里面:
protected $dbString='A';
B同A,如此。
ps. 用Yii一年多了,发个贴,冒个泡