【问题标题】:Forcing Eloquent models to re resolve database connection强制 Eloquent 模型重新解析数据库连接
【发布时间】:2015-05-06 08:43:56
【问题描述】:

有没有办法强制 Eloquent 模型重新解析它们被实例化的连接?

现在我有一个方法可以循环更改数据库连接:

foreach ($array as $key => $value) {

   Config::set('database.connections.mysql.database', $key . '_' . $database);

   $productRepo = new ProductRepository();    

   $products = $productRepo->all();

}

在产品存储库中,我调用 Eloquent 方法 all() 来获取数据库中的所有产品。

我发现连接已更改为数组中的第一个值,但在进一步执行循环时不会更改。

有什么办法可以强制 Eloquent 在运行时解析连接参数吗?

【问题讨论】:

    标签: laravel eloquent


    【解决方案1】:

    每个数据库实际上是一个单独的连接,所以我会在config/database.php文件中设置与数据库的所有连接,然后您可以使用模型上的setConnection()方法在它们之间切换。

    数据库.php:

    return [
        'default' => 'mysql-key1',
        'connections' => [
            'mysql-key1' => [
                'driver'    => 'mysql',
                'database'  => 'key1_dbname,
                // etc
            ],
            'mysql-key2' => [
                'driver'    => 'mysql',
                'database'  => 'key2_dbname',
                // etc
            ]
        ]
    ];
    

    ProductRepository.php:

    public function setConnection($name) {
        // assumes $this->product is your Product model
        $this->product->setConnection($name);
    }
    

    代码:

    $productRepo = new ProductRepository();
    foreach ($array as $key => $value) {
       $productRepo->setConnection($key . '_' . $database);
       $products = $productRepo->all();
    }
    

    编辑

    基于 cmets 的附加信息

    Laravel 只会在第一次需要时实例化与数据库的连接。创建连接后,它将重用它。如果您必须为每个查询重新连接到数据库,这将是一个巨大的性能问题。

    话虽如此,如果您真的想按照最初设计的方式进行操作,您只需在更新配置后调用DB::reconnect() 方法即可。

    foreach ($array as $key => $value) {
        Config::set('database.connections.mysql.database', $key . '_' . $database);
        DB::reconnect();
    
        $productRepo = new ProductRepository();
        $products = $productRepo->all();
    }
    

    但是,我强烈建议您考虑最初描述的选项,以免您进行大量不必要的连接。

    【讨论】:

    • 谢谢!这可以工作。但是我仍然不明白为什么模型仍然会引用第一个连接,即使它是动态更改的。希望有人能解释一下!
    • @yulun 我根据您的评论在答案中添加了一些信息。
    • 嘿@patricus,很抱歉重新讨论这个问题,但您知道方法 create() 的工作方式是否与查询方法不同吗?因为即使在模型上使用 setConnection() 之后,create() 方法仍然指向之前的数据库。
    • @yulun 问题是setConnection() 作用于类的实例,而create() 方法是类本身的静态方法。 create() 方法所做的只是用给定的属性实例化一个新实例,然后调用save()。因此,无需使用create(),您只需手动执行此操作:$productRepo = new ProductRepository($attributes); $productRepo->setConnection($key . '_' . $database); $productRepo->save(); 您还可以覆盖 ProductRepository 类上的 create() 方法以接受连接来执行此操作。
    • 以防万一其他人也遇到同样的问题 .. 您可以参考@patricus 提供的更好解释的答案stackoverflow.com/questions/29069101/…
    【解决方案2】:

    就我而言,我的每个数据库都没有数据库配置,因为它们是动态创建的。我使用了以下方法,只是更改了表名以包含数据库名称(这适用于 MySQL):

    foreach ($array as $key => $value) {
       $productRepo = new ProductRepository();  
       $productRepo->setTable($key . '_' . $database);  
       $products = $productRepo->all();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 2020-10-16
      • 1970-01-01
      • 2013-06-15
      • 2011-02-02
      • 1970-01-01
      • 2011-03-26
      相关资源
      最近更新 更多