Laravel 5.4 Многопользовательские миграции, переключение соединений для миграции
У меня есть мультитенантное приложение, в котором есть главная база данных с информацией о клиенте, в ней есть настройки для разных баз данных. Прочитав URL-адрес при запуске, я могу определить арендатора, к которому они обращаются, затем переключить соединение и кэшировать настройки, чтобы он использовал правильную базу данных арендаторов. Эта часть работает, но проблема возникает с миграциями.
Обычные миграции Laravel обрабатывают только главную таблицу, поэтому я добавил папку миграции для "арендаторов", которую необходимо запустить по всем арендаторам для каждого обновления. Для этого я использую следующий класс
<?php
namespace App\Console\Commands\Tenants;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class UpdateTenant extends Command
{
protected $signature = 'tenant:update {slug}';
protected $description = 'Update a tenants database';
protected $migrator;
public function __construct()
{
parent::__construct();
$this->migrator = app()->make('migrator');
}
public function fire()
{
$arguments = $this->arguments();
if ($account = DB::connection('root')->table('accounts')->where('slug', '=', $arguments['slug'])->first()) {
config()->set('database.connections.tenant.database', $arguments['slug']);
$this->migrator->setConnection('tenant');
if (! $this->migrator->repositoryExists()) {
$this->call('migrate:install', ['--database' => 'tenant']);
}
$this->migrator->run([$this->laravel->basePath() . '/' . 'database/tenants']);
foreach ($this->migrator->getNotes() as $note) {
$this->output->writeln($note);
}
}
}
}
Как вы можете видеть, это только для одного арендатора, определенного слизняком, у меня есть еще одна команда для цикла и вызова команды artisan для всех арендаторов.
foreach ($accounts as $account) {
$this->call('tenant:update', ['slug' => $account->slug]);
}
Проблема здесь в том, что, хотя проверка значения слага правильно находит правильную информацию о клиенте, соединение застревает на первом клиенте, несмотря на переключение соединения. Даже если я попытаюсь переключить его на корневой и обратно, просто игнорирует изменение конфигурации. Можно ли в любом случае сказать laravel сбросить соединение, чтобы оно использовало обновленные значения в конфигурации для повторного подключения?
1 answers
Отключитесь от текущего соединения между арендаторами с помощью:
config()->set('database.connections.tenant.database', $arguments['slug']);
DB::disconnect('tenant');<----- add this
$this->migrator->setConnection('tenant');
Это очистит подключение к ресурсам и заставит приложение восстановить себя с правильными настройками конфигурации.