Я пытаюсь использовать Laravel Eloquent ORM, чтобы сделать простое отношение один к одному на другом соединении.
Позвольте сказать сделать:
MyModel::on('secondary_connection')->get()
Это работает нормально.
Когда я делаю :
MyModel::on('secondary_connection')->with('AnotherModel')->get();
Я получаю сообщение об ошибке, потому что eloquent выполняет оператор SELECT AnotherModel для соединения по умолчанию (вместо «second_connection»).
Я не могу найти способ обойти это.
Мои модели хорошо определены, так как я могу присоединиться к ним по умолчанию.
Мысли?
Ну, мне предложили многие пользователи, кажется, что нет способа сделать это на лету. Мое понимание этого заключается в том, что Eloquent неполон, когда речь идет об управлении несколькими соединениями.
Есть 2 способа обойти это, я могу понять.
Сначала укажите соединение в модели:
class MyModel {
$protected connection = 'secondary_connection';
}
Это явно плохой обходной путь, так как эта модель может использоваться только в одном соединении … но все еще работает.
Затем, как предположил Ярек Ткачик, можно переключить соединение по умолчанию на новое. Но вместо того, чтобы делать это в файле конфигурации, можно поменять объект 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 Model, но включает в себя настройку соединения:
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());
Я тоже занимаюсь этим вопросом. Я нашел решение, но оно будет работать только в том случае, если допустимо настроить используемое соединение через файл .env. Это не будет работать, если вы хотите изменить его динамически, хотя в этом случае вы можете использовать немного логики (вызвать функцию), чтобы вернуть правильное имя соединения.
У меня есть решение переопределить метод connectionName класса Model. В моем случае у меня есть базовый класс для всех моих моделей, который заботится об этом:
abstract class ModelBase extends Model
{
public function getConnectionName()
{
return env('ELOQUENT_DB_CONNECTION', parent::getConnectionName());
}
}
Как я уже говорил, вы можете поместить любую нужную логику в getConnectionName, чтобы сделать ее более динамичной.
class MyModel {
$protected connection = 'secondary_connection';
}
Это хороший вариант, так как красноречивые модели — это фасады DB + дополнения. все функции фасадов DB также применимы к красноречивым моделям. поэтому вместо изменения соединения в фасаде базы данных мы можем изменить его здесь только без разницы.