Laravel Eloquent渴望加载不同的连接

时间:2015-02-09 19:18:06

标签: php laravel eloquent loading eager

我正在尝试使用Laravel Eloquent ORM在另一个连接上做一个简单的一对一关系。

让我们说:

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

这很好。

当我这样做时:

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

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

我无法找到解决这个问题的方法。

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

想法?

5 个答案:

答案 0 :(得分:2)

好吧我被许多用户建议,似乎没有办法在飞行中这样做。我对此的理解是,在管理多连接时,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方式中。

答案 1 :(得分:0)

实际上没有办法实现它。

您需要更改默认连接才能使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();
});

答案 2 :(得分:0)

我最终用更多的自定义onces替换了简单的关系函数。例如,我的->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-multiple-db-connections

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

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

答案 3 :(得分:0)

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

我的解决方案是覆盖Model类的connectionName方法。在我的情况下,我有一个基类用于我的所有模型,负责这个:

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

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

答案 4 :(得分:0)

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

是一个不错的选择,因为雄辩的模型是DB Facades + Extras。所有DB Facades功能也适用于雄辩的模型。因此,除了在db Facade中更改连接之外,我们可以在此处更改它,只是没有区别。