2013-11-04 173 views
3

我正在從一個Yii安裝中運行多個網站的項目。每個網站都有自己的數據庫,所以數據庫連接必須是動態的。動態更改數據庫連接Yii

我做了什麼,我創建了一個BeginRequestBehavior,它將啓動'onBeginRequest'。在這裏,我將檢查哪個URL已被調用,並確定匹配的數據庫(不在我的代碼中)並創建(或覆蓋)'db'組件。

<?php 
class BeginRequestBehavior extends CBehavior 
{ 

    /** 
    * Attaches the behavior object to the component. 
    * @param CComponent the component that this behavior is to be attached to 
    * @return void 
    */ 

    public function attach($owner) 
    { 

     $owner->attachEventHandler('onBeginRequest', array($this, 'switchDatabase')); 

    } 

    /** 
    * Change database based on current url, each website has his own database. 
    * Config component 'db' is overwritten with this value 
    * @param $event event that is called 
    * @return void 
    */ 

    public function switchDatabase($event) 
    { 
     // Here some logic to check which url has been called.. 

     $db = Yii::createComponent(array(
      'class' => 'CDbConnection', 
      'connectionString' => 'mysql:host=localhost;dbname=test', 
      'emulatePrepare' => true, 
      'username' => 'secret', 
      'password' => 'verysecret', 
      'charset' => 'utf8', 
      'enableProfiling' => true, 
      'enableParamLogging' => true 
     )); 

     Yii::app()->setComponent('db', $db); 

    } 
} 

它工作正常,但這是正確的方法?在其他方法中,我看到人們爲他們的模型創建自己的'MyActiveRecord'(擴展CActiveRecord)並將db組件放入屬性中。他們爲什麼這樣做?恐怕數據庫連接會以這種方式超出必要的次數。

回答

4

我用一個模型功能定義了數據庫連接:

public static $conection; // Model attribute 

public function getDbConnection(){ 

    if(self::$conection!==null) 
     return self::$conection; 

    else{ 
     self::$conection = Yii::app()->db2; // main.php - DB config name 

     if(self::$conection instanceof CDbConnection){ 
      self::$conection->setActive(true); 
      return self::$conection; 
     } 
     else 
      throw new CDbException(Yii::t('yii',"Active Record requires a '$conection' CDbConnection application component.")); 
    } 
} 

main.php

'db'=>array( 
    'connectionString' => 'mysql:host=192.168.1.*;dbname=database1', 
    'emulatePrepare' => true, 
    'username' => 'root', 
    'password' => 'password', 
    'charset' => 'utf8', 
    'enableProfiling'=>true, 
    'enableParamLogging' => true, 
), 
'db2'=>array(
    'class'=>'CDbConnection', 
    'connectionString' => 'mysql:host=192.168.1.*;dbname=database2', 
    'emulatePrepare' => true, 
    'username' => 'root', 
    'password' => 'password', 
    'charset' => 'utf8', 
), 
+0

我不需要多個數據庫,只有一個,它的變化取決於在你的網址上。你把db組件放在$ conection屬性中的原因是什麼? – davey

0

一個使用Yii當使用多個數據庫連接更涼爽方式:

換句話說,你需要1個主分貝來存儲用戶配置文件和數據庫連接;

對於其他從站數據庫,您需要一個設置;您將在需要時切換數據庫連接。我切換它在我的例如使用用戶ID。

我已經使用gii生成了一個從數據庫表的模型,我認爲你所有的從數據庫都具有相同的表結構,並且在該模型之上,我使用了另一個類,如下所示;

'db' => array(
     'class' => 'PortalDbConnection', 
     'connectionString' => 'mysql:host=localhost;dbname=mydb', 
     'username' => 'dev', 
     'password' => '123456', 
     'tablePrefix' => '', 
     'emulatePrepare' => true, 
     'enableParamLogging' => true, 
     'enableProfiling' => true, 
     'charset' => 'utf8', 
    ), 
    'dbx' => array(
     'connectionString' => 'mysql:host=localhost;dbname=mydb1', 
     'username' => 'dev', 
     'password' => '123456', 
     'charset' => 'utf8', 
     'tablePrefix' => '', 
     'autoConnect' => false, 
     'class' => 'CDbConnection', //this may be the reason you get errors! always set this 
    ), 

而現在,爲了你的模型的PHP代碼:

<?php 

class DomainSlaveM extends Domain { 

    public static function model($className = __CLASS__) { 
     return parent::model($className); 
    } 

    public static $server_id = 1; 
    public static $slave_db; 

public function getDbConnection() { 
    self::$slave_db = Yii::app()->dbx; 
    if (self::$slave_db instanceof CDbConnection) { 
     self::$slave_db->active = false; 
     $config = require(Yii::app()->getBasePath() . '/config/location/flavius.php'); 
     $connectionString = $config['components']['dbx']['connectionString']; 
     self::$slave_db->connectionString = sprintf($connectionString, self::$server_id); 
     self::$slave_db->setActive(true); 
     return self::$slave_db; 
    } 
    else 
     throw new CDbException(Yii::t('yii', 'Active Record requires a "db" CDbConnection application component.')); 
} 

    } 

,並使用它像這樣:

public function createDomainSlaveM($model) { 
//switch the db connection; $server_id gets values, from 1 to N 
      DomainSlaveM::$server_id = $model->user_id; 
      $model_domain_slave_m = new DomainSlaveM(); 
      $model_domain_slave_m->attributes = $model->attributes; 
      if ($model_domain_slave_m->validate() && $model_domain_slave_m->save()) { 
       //ok 
      } else { 
       //bad 
      } 
     } 
+0

我知道我可以這樣做,但在我的情況下,我不需要多個數據庫,只有一個,這取決於你的網址。 – davey