Ad

Dynamic Env-files (multiple Databases) And Artisan Commands

- 1 answer

I have a large project which will have each customer on their own separate database. To get this to work we use a custom .env-loader that loads each customers .envby checking the customers subdomain (unique to each customer).

However, of course this doesn't work with artisan commands. For instance, when I want to migrate, I will need to migrate all databases at once. So I've set up an Artisan command that fetches the .env-files and loop through them and then calls the default artisan migrate. But it is not working as expected.

I've tried everything; for instance:

$dotenv = new Dotenv('/env', '.test.env');
$dotenv->overload();

And:

app()->useEnvironmentPath('/env');
app()->loadEnvironmentFrom('.test.env');

And even:

config('database.connections.mysql.database', 'test_database');

As soon as I run $this->call('migrate'); the app defaults to the default .env and ignores all customizations at runtime. Does anyone have an idea on how I can overload the migration commands choice of database?

Note: I know that I can manually setup multiple connections in config/database.php (for instance like: Overriding Defauiding-default-laravel-database-configuration-for-artisan-migrate-commands">Overriding Default Laravel database configuration for artisan migrate commands), however, image a few dozen customers and this would not be viable.

Ad

Answer

After a whole lot of issues I was able to sort it this way;

In Laravel 5 there seem to be a difference in Config::set(), config('config',['key' => 'value]) and config()-set('config', ['key' => 'value']).

After a lot of testing different variant we managed to get a solution this way;

$connection = 'connection';
$iterator = 0;

foreach ($files as $file) {
    App::useEnvironmentPath('/env');
    App::loadEnvironmentFrom('.file.env');

    // Create a new connection "on the fly"
    config()->set('database.connections.' . $connection . '_' . $iterator, [
        'driver'    => 'mysql',
        'host'      => env('DB_HOST'),
        'database'  => env('DB_DATABASE'),
        'username'  => env('DB_USERNAME'),
        'password'  => env('DB_PASSWORD'),
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix'    => '',
        'strict'    => false,
    ]);

    // Call regular migration command
    $this->call('migrate', ['--force' => true, '--database' => $connection . '_' . $iterator]);

    $iterator++;
}

This manages to set multiple new connections to the MySQL-database, and then seed each one of them.

Thanks to @David Allen here for the inspiration.

Ad
source: stackoverflow.com
Ad