Laravel: Run migrations on another database

前端 未结 8 2065
有刺的猬
有刺的猬 2020-12-29 23:15

In my app every user has its own database that created when user registered. Connection and database data (database name, username, password) are saved in a table in default

8条回答
  •  时光取名叫无心
    2020-12-29 23:40

    I actually faced the same problem and the answer of Joe did not work in my case, as I have different database connections (so different host, port, user and pass).

    Therefore the migration must do a lot of reconnects all the time:

    • Migration starts with default database (in my case that is client_1)
    • Fetches stuff from table migrations and clients
    • Disconnect default database
    • Connect to database of client_2, run migration parts, disconnect client_2
    • Connect to default database again, store migration "log"

    And then loop it for each client.

        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            $defaultConnection = BackendConfig::getDatabaseConfigArray();
            $clients = ClientController::returnDatabasesForArtisan();
    
            foreach ($clients as $client) {
                BackendConfig::setDatabaseFromClient($client);
    
                Schema::create('newtable', function (Blueprint $table) {
                    $table->increments('id')->unsigned();
                    $table->timestamps();
                });
                BackendConfig::setDatabaseFromArray($defaultConnection);
            }
        }
    

    And the class where the magic is stored:

    class BackendConfig
    {
        public static function getDatabaseConfigArray($client_id = 1)
        {
            $connection = config('database.default');
    
            return [
                'id' => $client_id,
                'host' => config("database.connections.$connection.host"),
                'port' => config("database.connections.$connection.port"),
                'username' => config("database.connections.$connection.username"),
                'password' => config("database.connections.$connection.password"),
            ];
        }
    
        public static function setDatabaseFromArray($array)
        {
            self::setDatabase($array['id'], $array['host'], $array['port'], $array['username'], $array['password'], true);
            DB::disconnect();
        }
    
        public static function setDatabaseFromClient(Client $client)
        {
            DB::disconnect();
            self::setDatabase($client->id, $client->database->host, $client->database->port, $client->database->username, $client->database->password, true);
        }
    
        public static function setDatabase($client_id, $host, $port, $username, $password)
        {
            $connection = config('database.default');
    
            $database_name = $connection . '_' . $client_id;
    
            config([
                "database.connections.$connection.database" => $database_name,
                "database.connections.$connection.host" => $host,
                "database.connections.$connection.port" => $port,
                "database.connections.$connection.username" => $username,
                "database.connections.$connection.password" => $password,
            ]);
    }
    

    With this solution I can run the exact same migrations on every client, yet the migration is just stored in client_1, my sort of master client.

    However, pay attention to the two DB::disconnect();. It will screw up the situation without those as then migrations logs are stored in another client's database or such.

    Ah and by the way, ClientController does nothing special:

    public static function returnDatabasesForArtisan()
    {
        return Client::select('*')->with('database')->get();
    }
    

提交回复
热议问题