繁体   English   中英

Laravel Eloquent 在不同的连接上预先加载

[英]Laravel Eloquent eager loading on a different connection

我正在尝试使用 Laravel Eloquent ORM 在两个不同的连接上建立简单的一对一关系。

假设我这样做:

MyModel::on('secondary_connection')->get()

那工作正常。

当我做 :

MyModel::on('secondary_connection')->with('AnotherModel')->get();

我收到一个错误,因为 eloquent 正在对默认连接(而不是“secondary_connection”)执行 AnotherModel SELECT 语句。

我找不到解决此问题的方法。

我的模型定义明确,因为我可以在我的默认连接中加入它们。

想法?

好吧,正如许多用户所建议的那样,似乎没有办法即时执行此操作。 我的理解是 Eloquent 在管理多连接方面是不完整的。

我能想到有两种方法可以解决这个问题。

首先,在模型中指定连接:

class MyModel {
    $protected connection = 'secondary_connection';
}

这显然是一个糟糕的解决方法,因为这个模型只能在一个连接中使用……但仍然有效。

然后,正如 Jarek Tkaczyk 建议的那样,可以将默认连接切换为新连接。 但不是在配置文件中执行此操作,而是可以交换 PDO 对象。

    $default = DB::getPdo(); // Default conn
    $secondary = DB::connection('secondary_connection')->getPdo();
    DB::setPdo($secondary);
    $result = MyModel::with('AnotherModel')->get();
    DB::setPdo($default);

这是一种有效的解决方法,并且可以是一个干净的解决方案。 下一步是把这个切换机制放在一个很好的 Laravel 方式中。

几乎没有办法在飞行中做到这一点。

您需要更改默认连接,以便 Eloquent 将其用于预先加载的模型。 您可以将其包装在这样的辅助方法中:

function on($connection, Closure $callback)
{
    // backup default connection
    $default = Config::get('database.default');

    // change for current query
    Config::set('database.default', $connection);

    // run the query
    $result = $callback();

    // restore the default connection
    Config::set('database.default', $default);

    return $result;
}

然后就像下面这样调用:

$models = on('secondary_connection', function () {
   return MyModel::with('relation')->get();
});

我最终用更多的自定义函数替换了简单的关系函数。 例如,我的->relatedModel是 Eloquent 模型中原始模型的副本,但包括设置连接:

public function relatedModel() {
  $instance = new \relatedModel;
  $instance->setConnection($this->getConnectionName());
  $query = $instance->newQuery();

  return new BelongsTo($query, $this, 'myForeignKey', $instance->getKeyName(), null);
}

我在 Laravel 5 上,所以这可能与 4.2 不同。

而且由于我现在经常摆弄这个问题,这是通过默认连接以外的另一个连接完成验证的好方法: http : //laravel.io/forum/10-29-2014-validation-rules-and-多数据库连接

如果是模型方法,您甚至可以将其缩短为:

$v = Validator::make($data, $rules);
$v->getPresenceVerifier()->setConnection($this->getConnectionName());

我也在处理这个问题。 我找到了一个解决方案,但它只有在可以通过 .env 文件配置使用的连接时才有效。 如果您想动态更改它,这将不起作用,尽管在这种情况下您可以使用一些逻辑(调用函数)来返回正确的连接名称。

我的解决方案是覆盖 Model 类的 connectionName 方法。 在我的情况下,我的所有模型都有一个基类来处理这个问题:

abstract class ModelBase extends Model
{
    public function getConnectionName()
    {
        return env('ELOQUENT_DB_CONNECTION', parent::getConnectionName());
    }
}

正如我所提到的,您可以在 getConnectionName 中放入任何您想要的逻辑,这样您就可以使其更具动态性。

class MyModel {
    $protected connection = 'secondary_connection';
}

是一个不错的选择,因为雄辩的模型是 DB Facades + extras。 所有 DB Facades 功能也适用于 eloquent 模型。 因此,我们可以在这里更改它而不是更改 db 外观中的连接,只是没有区别。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM