多数据库连接和 Yii 2.0

Posted

技术标签:

【中文标题】多数据库连接和 Yii 2.0【英文标题】:Multiple database connections and Yii 2.0 【发布时间】:2015-01-31 00:02:42 【问题描述】:

我有两个数据库,每个数据库都有相同字段的同一张表,但是如何在Yii2.0 中同时从所有两个数据库中获取所有记录?

【问题讨论】:

【参考方案1】:

首先你需要像下面这样配置你的数据库:

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();

【讨论】:

提前感谢您的出色回答。这真的很有帮助。 使用您的代码时出现错误。这不是完全错误的,但我认为你错过了一些东西。你在返回后遗漏了 "'class' => 'yii\db\Connection'" [ 伟大的!!竖起大拇指。 我是唯一一个在 ActiveRecord 中拥有静态方法并且不能用非静态方法覆盖它的人吗? 应该是 public static function getDb() 使用 static 因为它是覆盖静态方法。【参考方案2】:

只需添加: 我按照提供的答案进行操作,但仍然出现错误: "未知组件 ID:db"

经过一些测试,我发现:函数 getDB 仅在之后调用了与 db 的连接。因此,您不能在配置文件中删除或重命名“db”。相反,您需要让对“db”的调用正常进行,然后再覆盖它。

解决方案(对我来说)如下:

config/web.php 中,在db 下添加您的第二个数据库配置,如下所示:

'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。找不到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'),

谢谢

【讨论】:

我重命名了 'db' 并且它起作用了。除此之外,您的解决方案还有效。 我试过你的,但我得到了SQLSTATE[42000]: [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Incorrect syntax near '='. The SQL being executed was: SET time_zone = '+00:00',知道吗?谢谢【参考方案3】:

我们的情况有点复杂,我们有一个“父”数据库,其中有一个表,其中包含一个或多个“子”数据库的名称。 原因是 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

【讨论】:

【参考方案4】:

如果您使用schmunk42/yii2-giiant 生成模型类,则可以设置'modelDb' 属性以使用'db' 以外的数据库组件。

【讨论】:

以上是关于多数据库连接和 Yii 2.0的主要内容,如果未能解决你的问题,请参考以下文章

Yii2.0连接多个数据库

HTTP 2.0 - 1 个 TCP/IP 连接与 6 个并行

YII with()

Yii2 HOW-TO:PDO连接数据库错误

在控制器中更改 ASP.NET Core 2.0 标识连接字符串

YII2.0安装教程,数据库配置前后台 [ 2.0 版本 ]