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 сбросить соединение, чтобы оно использовало обновленные значения в конфигурации для повторного подключения?

Author: Jordan Ramstad, 2017-06-14

1 answers

Отключитесь от текущего соединения между арендаторами с помощью:

config()->set('database.connections.tenant.database', $arguments['slug']); 
DB::disconnect('tenant');<----- add this
$this->migrator->setConnection('tenant');

Это очистит подключение к ресурсам и заставит приложение восстановить себя с правильными настройками конфигурации.

 2
Author: , 2017-06-15 16:37:06