Search code examples
phplaravellaravel-5laravel-artisanartisan-migrate

Artisan Call in Loop


I have a custom console command that needs to loop through some companies and make a database for each. The command works now, but only once. It does not run the migration the second time around in the loop. So basically if I have 2 blank DBs (db_one and db_two) the config runs and migrates the first time for db_one and when the loop runs again, nothing happens to db_two. If I replace the console command to just echo out the DB name it returns both so I know its not the loop. Also if I log out the db used in each connection of the loop, its the correct DB.

Here is the command:

public function handle()
{
    $companies = Company::all();

    foreach( $companies as $company)
    {
        \Config::set('database.connections.company.database', $company->db_name);

        Artisan::call( 'migrate', [
            '--database' => 'company',
            '--path' => 'database/migrations/company',
        ]);

        $this->info(  config('database.connections.company.database') );

    }
}

log error:

local.ERROR: Database [10_barrel] not configured. {"userId":1,"email":"[email protected]","exception":"[object] (InvalidArgumentException(code: 0): Database [db_2] not configured. at /Users/Sites/cheers/vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php:140)

database.php

'connections' => [

        'main' => [
            'driver' => 'mysql',
            'host' => env('MAIN_DB_HOST', '127.0.0.1'),
            'port' => env('MAIN_DB_PORT', '3306'),
            'database' => env('MAIN_DB_DATABASE', 'forge'),
            'username' => env('MAIN_DB_USERNAME', 'forge'),
            'password' => env('MAIN_DB_PASSWORD', ''),
            'unix_socket' => env('MAIN_DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],

        'company' => [
            'driver' => 'mysql',
            'host' => env('COMPANY_DB_HOST', '127.0.0.1'),
            'port' => env('COMPANY_DB_PORT', '3306'),
            'database' => '',
            'username' => env('COMPANY_DB_USERNAME'),
            'password' => env('COMPANY_DB_PASSWORD'),
            'unix_socket' => env('COMPANY_DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],
]

env:

COMPANY_DB_HOST=127.0.0.1
COMPANY_DB_PORT=3306
COMPANY_DB_USERNAME=root
COMPANY_DB_PASSWORD=

Solution

  • It was quite interesting. I need to say I wasn't able to fully reproduce your error (I didn't get any error in log) but for sure migration is run only for 1st loop iteration.

    First thing instead of:

    Artisan::call
    

    I would recommend you to use:

    $this->call
    

    you will get extra output what is really going.

    But the most important thing to make it work is to disconnect from database and purging the connection. Otherwise Laravel won't see that you changed your database name in configuration and will use old database.

    So you should add:

    $this->laravel['db']->purge('company');
    

    at the end of loop to make it possible to run migrations like this.

    I've tested it and it's working for me without any problem.