20

I work in a project that uses multiple databases. It seems like Laravel only uses the migrations-table in the database that is set as default. I would like one migrations table per database that logs the migrations that have been done to that specific database. Is this possible?

I have defined the databases in the config like this:

'connections' => [
    'db1' => array(
        'driver'    => 'mysql',
        'host'      => 'db1.host',
        'database'  => 'db1',
        'username'  => 'username',
        'password'  => 'password',
    ),
    'db2' => [
        'driver'    => 'mysql',
        'host'      => 'db2.host',
        'database'  => 'db2',
        'username'  => 'username',
        'password'  => 'password',
    ]
],

I also made the first database (db1) the default one

'default' => 'db1'

I install the migrations table on both databases

artisan migrate:install --database=db1
artisan migrate:install --database=db2

After that i proceed to create a couple of database specifc migrations

Create table test1 in db1 database:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateTest1Table extends Migration
{
    public function up()
    {
        Schema::connection('db1')->create('test1', function(Blueprint $table)
        {
            $table->increments('id')->unsigned();
        });
    }

    public function down()
    {
        Schema::connection('db1')->drop('test1');
    }
}

Create table test2 in db2 database:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateTest2Table extends Migration
{
    public function up()
    {
        Schema::connection('db2')->create('test2', function(Blueprint $table)
        {
            $table->increments('id')->unsigned();
        });
    }

    public function down()
    {
        Schema::connection('db2')->drop('test2');
    }
}

I now run the migrations

artisan migrate

Expected outcome

db1.migrations

+-----------------------------+-------+
| migration                   | batch |
+-----------------------------+-------+
| create_test1_table_in_db1   |     1 |
+-----------------------------+-------+

db2.migrations

+-----------------------------+-------+
| migration                   | batch |
+-----------------------------+-------+
| create_test2_table_in_db2   |     1 |
+-----------------------------+-------+

Actual outcome

db1.migrations

+-----------------------------+-------+
| migration                   | batch |
+-----------------------------+-------+
| create_test1_table_in_db1   |     1 |
| create_test2_table_in_db2   |     1 |
+-----------------------------+-------+

db2.migrations

+-----------------------------+-------+
| migration                   | batch |
+-----------------------------+-------+
Empty set
codeaken
  • 844
  • 1
  • 8
  • 20
  • 1
    Just realized that it might be a bad idea to have a migrations-table for each database in regards to rollbacks. Lets say you have three databases and the latest migration caused changes to two of them. When you want to rollback you no longer know what databases you need to rollback on since there's no longer a global batch number. Thoughts? – codeaken Oct 30 '14 at 18:16
  • It mostly depends on your needs. If you have your a single application with the data storage structure distributed between multiple servers (for performance or whatever other reasons you may have), then one common migration file is all you need. If however you have smaller applications/modules that might only use databases on one server and you want to update them independently, then having separate migration tables would be beneficial (keep in mind that `migrate:rollback` also has the `--database` parameter). – Bogdan Oct 30 '14 at 18:33

1 Answers1

49

Article on usage of multiple database usage in Laravel - https://stackcoder.in/posts/laravel-7x-multiple-database-connections-migrations-relationships-querying

Use the --database parameter with the migrate command and store the migrations for each database in separate directories.

You could have separate directories in app/database/migrations for each of your database (in your case db1 and db2) and store the appropriate migrations in each directory. Then you could run the migrations like this:

artisan migrate --database="db1" --path="app/database/migrations/db1"
artisan migrate --database="db2" --path="app/database/migrations/db2"

This way your migrations table will be independent for each database.

If you want to go the extra mile and automate the process you could create your custom command that will run all the migrations at once. You can create the command like this (use make:console for Laravel 5.0 up to 5.2 or make:command for Laravel 5.2+):

artisan command:make MigrateAllCommand --command=migrate:all

This will create a new file app/commands/MigrateAllCommand.php. Your command's fire method would look something like this:

public function fire()
{
    foreach (Config::get('database.connections') as $name => $details)
    {
        $this->info('Running migration for "' . $name . '"');
        $this->call('migrate', array('--database' => $name, '--path' => 'app/database/migrations/' . $name));
    }
}

This will work provided the name of the database configuration key is the same as the migration directory name. You can then just call it like this:

artisan migrate:all

You can check the Laravel Command Docs for more info.

Channaveer Hakari
  • 2,769
  • 3
  • 34
  • 45
Bogdan
  • 43,166
  • 12
  • 128
  • 129