'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]
Roll back all the migrations (or start with a fresh database);
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);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:
- Create Command class with:
php artisan make:command NameClass
- Go to
app/Console/Commands/
and find the class fileNameClass.php
- In the NameClass.php you have two attributes
$signature
(the name of the command) and$description
(Information about what your command does). - Set the name and the description of your command.
Ex: protected $signature='namecommand'; protected $descripton = 'This method migrate tables in order'
- 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. - Register your command. Go to
app/Console/Kernel.php and
add your class to the list of Command Classes.protected $commands = [ Commands\NameClass::class, ];
- Write the command in the terminal.
php artisan namecommand
Example:
php artisan make:command MigrateInOrder
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 ,
]);
}
}
}
- Go to app/Console/Kernel.php and register your command
protected $commands = [
Commands\MigrateInOrder::class,
];
- 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 |