'Laravel change migration order

Is there a way how I can change the migrations order without remaking them all? Because now I have a problem with my foreign keys -_- (working with laravel)



Solution 1:[1]

  1. Roll back all the migrations (or start with a fresh database);

  2. Change the dates that form the first part of the migration filenames so they're in the order you want (eg. for 2014_06_24_134109_update_database.php, the date & time is 2014-06-24, 13:41:09);

  3. Run the migrations again.

With respect to your comment about foreign keys... I'm not sure that the problem is with Laravel. More likely, it's just MySQL.

I avoid foreign keys because once you get a moderately complicated set of relations, you start to run into problems with database consistency like you're seeing - it's hard for the server to figure out what order to create the tables & relationships in, and it starts to cause difficulties with things like dump files (for backups).

Solution 2:[2]

You have to create a custom command that executes php artisan migrate:refresh --path=/database/migrations/name_migration.php repeately with the migrations's name in the order you want.

Like this:

  1. Create Command class with: php artisan make:command NameClass
  2. Go to app/Console/Commands/ and find the class file NameClass.php
  3. In the NameClass.php you have two attributes $signature (the name of the command) and $description (Information about what your command does).
  4. Set the name and the description of your command.Ex: protected $signature='namecommand'; protected $descripton = 'This method migrate tables in order'
  5. Inside the NameClass.php you have a method called handle(), here you have to declare the code you want to be executed when you write the command.
  6. Register your command. Go to app/Console/Kernel.php and add your class to the list of Command Classes. protected $commands = [ Commands\NameClass::class, ];
  7. Write the command in the terminal. php artisan namecommand

Example:

  1. php artisan make:command MigrateInOrder

  2. app/Console/Commands/MigrateInOrder.php

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class MigrateInOrder extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'migrate_in_order';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Execute the migrations in the order specified in the file app/Console/Comands/MigrateInOrder.php \n Drop all the table in db before execute the command.';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
       /** Specify the names of the migrations files in the order you want to 
        * loaded
        * $migrations =[ 
        *               'xxxx_xx_xx_000000_create_nameTable_table.php',
        *    ];
        */
        $migrations = [ 
                        '2020_04_18_005024_create_users_types.php',
                        '2014_10_12_000000_create_users_table.php',
                        '2014_10_12_100000_create_password_resets_table.php',
                        '2019_08_19_000000_create_failed_jobs_table.php'
        ];

        foreach($migrations as $migration)
        {
           $basePath = 'database/migrations/';          
           $migrationName = trim($migration);
           $path = $basePath.$migrationName;
           $this->call('migrate:refresh', [
            '--path' => $path ,            
           ]);
        }
    }
} 
  1. Go to app/Console/Kernel.php and register your command
    protected $commands = [
        Commands\MigrateInOrder::class,
    ];
  1. Excute the command
   php artisan migrate_in_order

Solution 3:[3]

The best and easiest thing would be to just rename the migration yyyy_mm_dd_hhmmss_migration_name. If your migration follows this sequence, Laravel will ensure to run the migration is sorted form of date,

Solution 4:[4]

Taking inspiration from PhpMyAdmin, I put all foreign keys definitions in a specific far future file, eg : 2999_12_31_235959_foreign_key.php

<?php

use App\Models\Post;
use App\Models\Tag;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class ForeignKeys extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        // Post_tag
        Schema::table(Post::NOM, function (Blueprint $table) {
            $table->foreign('id_post')
                ->references('id_post')
                ->on(Post::NOM);

            $table->foreign('id_tag')
                ->references('id_tag')
                ->on(Tag::NOM);
        });
    }
}

The only con I see is not having foreign keys definition in migration.

For the pros :

  • Keeping database relations
  • Do not care of table creation order

Solution 5:[5]

Building on the answer of Galeokerdo which suggests creating a separate migration file for the foreign keys, and putting the date in the far future, I tried it and it worked great. But then I started thinking of the rollback. It turned out that Laravel takes the reverse order when rolling back migrations. That is, the latest file is rolled back first.

Since the rollback will not work with the foreign key constraints in place, I tried putting my foreign-key-removal code in the "down" method of the separate foreign key migration, having found out that the file will execute first before all other migration files. Like thus:

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
   Schema::table('tablename', function (Blueprint $table) {
       $table->dropForeign('tablename_foreignkey_foreign');
   });
}

"tablename_foreignkey_foreign" is the name of the foreign key constraint. By default, it is 
"nameofthetable_foreignkeycolumn_foreign"

I just wanted to share this in case anybody is struggling with it the way I did.

Solution 6:[6]

You only need to change migrations order. if bands or stage tables are below users table, MySQL don't find the references. =)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tiago Martins Peres
Solution 2 Priscila Ibarra
Solution 3 David Buck
Solution 4 Galeokerdo
Solution 5 Stephen Adelakun
Solution 6 Vogel Coage