web-dev-qa-db-ja.com

複数のデータベース接続とYii 2.0

2つのデータベースがあり、すべてのデータベースに同じフィールドを持つ同じテーブルがありますが、 Yii 2.0で2つのデータベースすべてから同時にすべてのレコードを取得するにはどうすればよいですか?

54
Chhorn Soro

まず、次のようにデータベースを構成する必要があります。

_return [
'components' => [
    'db1' => [
        'class' => 'yii\db\Connection',
        'dsn' => 'mysql:Host=localhost;dbname=db1name', //maybe other dbms such as psql,...
        'username' => 'db1username',
        'password' => 'db1password',
    ],
    'db2' => [
        'class' => 'yii\db\Connection',
        'dsn' => 'mysql:Host=localhost;dbname=db2name', // Maybe other DBMS such as psql (PostgreSQL),...
        'username' => 'db2username',
        'password' => 'db2password',
    ],
],
];
_

次に、次のことができます。

_// To get from db1
Yii::$app->db1->createCommand((new \yii\db\Query)->select('*')->from('tbl_name'))->queryAll()

// To get from db2
Yii::$app->db2->createCommand((new \yii\db\Query)->select('*')->from('tbl_name'))->queryAll()
_

アクティブなレコードモデルを使用している場合、モデルで以下を定義できます。

_public static function getDb() {
    return Yii::$app->db1;
}

//Or db2
public static function getDb() {
    return Yii::$app->db2;
}
_

次に:

getDb()メソッドで_db1_を設定している場合、結果は_db1_などから取得されます。

_ModelName::find()->select('*')->all();
_
102

追加するだけ:提供された答えに従いましたが、まだエラーが発生しました:「不明なコンポーネントID:db」

いくつかのテストの後、ここに私が発見したものがあります:getDB関数は[〜#〜] after [〜#〜]のみと呼ばれ、dbへの接続が行われます。したがって、構成ファイル内の「db」を削除または名前変更することはできません。代わりに、「db」の呼び出しを通常どおり続行し、その後でそれをオーバーライドする必要があります。

解決策(私にとって)は次のとおりでした:

config/web.phpで、次のようにdbの下に2番目のデータベース構成を追加します。

'db' => require(__DIR__ . '/db.php'),
'db2' => [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:Host=localhost;dbname=name',
    'username' => 'user',
    'password' => 'password',
    'charset' => 'utf8',
    'on afterOpen' => function ($event) {
        $event->sender->createCommand("SET time_zone = '+00:00'")->execute();
    },
],

dbの名前を変更しないでください。データベースが見つからないと、エラーが発生します。 db2という名前を付けることができます。

次に、モデルに次のコードを追加します。

class ModelNameHere extends \yii\db\ActiveRecord {

   // add the function below:
   public static function getDb() {
       return Yii::$app->get('db2'); // second database
   }

これにより、デフォルトのdb構成がオーバーライドされます。

それが他の誰かに役立つことを願っています。

注:db2の構成を別のファイルに含めることはできますが、db.phpファイルに含めることはできません(明らかに)。代わりに、db2.phpというファイルを作成し、dbと同様に呼び出します。

'db' => require(__DIR__ . '/db.php'),    
'db2' => require(__DIR__ . '/db2.php'),

ありがとう

19
DrBorrow

私たちの状況はもう少し複雑です。1つ以上の「子」データベースの名前を含むテーブルを持つ「親」データベースがあります。この理由は、Yiiプロジェクトが各クライアントに対してインスタンス化され、子データベースの数はクライアントに依存し、データベース名は任意ですが(パターンに従っています)。

したがって、次のように\yii\db\ActiveRecordをオーバーライドします。

class LodgeActiveRecord extends \yii\db\ActiveRecord
{

public static function getDb()
{
    $lodgedb = Yii::$app->params['lodgedb'];
    if(array_key_exists( $lodgedb, Yii::$app->params['dbs'])) {
        return Yii::$app->params['dbs'][ $lodgedb ];
    }
    $connection = new \yii\db\Connection([
        'dsn' => 'mysql:Host=localhost;dbname=' . $lodgedb,
        'username' => Yii::$app->params['dbuser'],
        'password' => Yii::$app->params['dbpasswd'],
        'charset' => 'utf8',
    ]);
    $connection->open(); // not sure if this is necessary at this point
    Yii::$app->params['dbs'][ $lodgedb ] = $connection;
    return $connection;
}

}

データベース関数を呼び出す前に、最初にYii::$app->params['lodgedb']を必要なデータベースの名前に設定します。

Yii::$app->params['lodgedb'] = $lodge->dbname; // used by LodgeActiveRecord

モデルクラスは、LodgeActiveRecordから拡張される以外は変更されません。

class BookingRooms extends \app\models\LodgeActiveRecord

1
Nik Dow

schmunk42/yii2-giiant を使用してモデルクラスを生成している場合、'modelDb'以外のデータベースコンポーネントを使用するように設定できる'db'プロパティがあります。

0
gvlasov