原文:http://www.yiiframework.com/wiki/123/multiple-database-support-in-yii

在Yii应用的配置文件 protected/config/main.php 中通常只有一个数据库配置段落,不过要让它支持多个数据库,并且让不同的Model绑定到不同的数据库也很简单的。

我们将在官方blog示例程序上增加一个独立的广告数据库,虽然广告数据库和博客是关联的,但它仍然是一个独立的系统。

建立配置 

首先在配置文件的第一个数据库配置段落之后增加一个新的数据库段落,当然你可以把它叫做db2,但是为了可读性我们把它命名为 dbadvert。

  1. // protected/main/config.php 
  2.  
  3.  
  4.  
  5. return array
  6.  
  7. ... 
  8.  
  9. 'components' => array
  10.  
  11. 'db'  => array
  12.  
  13. 'connectionString' => 'mysql:host=dbserver1;dbname=my1db'
  14.  
  15. ... 
  16.  
  17. ), 
  18.  
  19. 'dbadvert' => array
  20.  
  21. 'connectionString' => 'mysql:host=adserver2;dbname=advertisingDB'
  22.  
  23. 'username' => 'advertuser'
  24.  
  25. 'password' => '***********'
  26.  
  27. ... 
  28.  
  29. 'class' => 'CDbConnection' // DO NOT FORGET THIS! 
  30.  
  31. ), 
  32.  
  33. ... 

它的参数和默认数据库配置段落的参数基本一致,不同的是必须增加一个class参数,这样Yii才能知道您定义的这个段落是数据库配置,否则配置无法成功。

完成以上设置后,你就可以像使用 Yii::app()->db 一样使用 Yii::app()->dbadvert 来调用你的第二个数据库了。

但是我们可以做的不仅仅是这些,还包括对GII工具和Active Record的支持。

使用Gii

Gii只能支持使用默认数据库连接快速建立 models/controllers/crud 等代码,所以你需要临时地将protected/config/main.php 文件中的广告数据库修改成默认数据库连接:

  1. // protected/config/main.php 
  2.  
  3. 'components' => array
  4.  
  5. 'db' => array
  6.  
  7. 'connectionString' => 'mysql:host=dbserver1;dbname=my1db'
  8.  
  9. # ... 
  10.  
  11. #  ), 
  12.  
  13. // TEMPORARY (put back to 'dbadvert' when done) 
  14.  
  15. 'db' => array
  16.  
  17. 'connectionString' => 'mysql:host=adserver2;dbname=advertisingDB'

完成以上操作后,你就可以使用Gii工具来创建你需要的代码了,完成后别忘记将数据库配置欢迎哦!

GetDbConnection() override

所有定义的 protected/models/*.php Model都在其父类中包含一个getDbConnection()的方法,它返回主数据库的连接对象。我们需要在新数据库关联的Model定义中覆写这个方法,让这个方法返回新数据的连接对象。

当然可以在Model定义文件自身中完成覆写,但是当存在多个类似Mode时,每个Model都需要一段覆写代码,这就没有必要了。最好另外定义一 个CActiveRecord对象的包装类,在这个包装类中加入getDbConnection()的覆写方法,相关Model定义从这个包装类下继承, 这样代码可读性维护性都大大提高了。

自定义包装类得方法在此文章中另有讲解,我们假定已经定义好了 protected/components/MyActiveRecord.php,将新数据的关联Model修改为继承自MyActiveRecord,而不是默认的CActiveRecord。

  1. //  protected/components/MyActiveRecord.php 
  2.  
  3.  
  4.  
  5. class MyActiveRecord extends CActiveRecord { 
  6.  
  7. ... 
  8.  
  9. private static  $dbadvert = null; 
  10.  
  11.  
  12.  
  13. protected static  function  getAdvertDbConnection() 
  14.  
  15.  
  16. if  (self::$dbadvert !== null) 
  17.  
  18. return self::$dbadvert
  19.  
  20. else 
  21.  
  22.  
  23. self::$dbadvert = Yii::app()->dbadvert; 
  24.  
  25. if (self::$dbadvert instanceof  CDbConnection) 
  26.  
  27.  
  28. self::$dbadvert->setActive(true); 
  29.  
  30. return self::$dbadvert
  31.  
  32.  
  33. else 
  34.  
  35. throw new  CDbException(Yii::t('yii','Active Record requires a "db" CDbConnection application component.')); 
  36.  
  37.  
  38.  
  39. ... 

注意,这个覆写类是特意设为static的。现在一切准备好了,我们来修改Model自身的定义代码吧:

  1. // protected/models/Ad.php 
  2.  
  3.  
  4.  
  5. class Ad extends  MyActiveRecord { 
  6.  
  7. ... 
  8.  
  9. public  function  getDbConnection() 
  10.  
  11.  
  12. return  self::getAdvertDbConnection(); 
  13.  
  14.  
  15. ... 

现在这个Model就可以正确地连接到广告数据库,而不是默认的blog数据库了。