yiisoft / yii2

Yii 2: The Fast, Secure and Professional PHP Framework
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
14.23k stars 6.91k forks source link

Suggestion: A way to execute migrations in a specified order #13119

Closed traykovn closed 7 years ago

traykovn commented 7 years ago

Use-case

I have an advanced yii2 project working on production. At some point in time I decided to pull out the reusable code from the project and put it in modules. That's why currently I have around 10 modules. These modules contain new migrations, because the tables for each module are new, with names following different convention, new columns and so on. The migrations work perfectly locally, because the timestamps of the migrations are in order.

Problem

Now I have to copy the whole project to another production environment. If I run the migrations, the migrations of the main project will execute first (because they are older) and migration process will fail, because they depend on module's tables (for example the user table is in yii2-user module). Now I have to go to each module and rename all migrations to be in the correct order. This means every migration file, every migration class name, and then I have go to the database and change the records in the local migration table. Furthermore I have to keep track which module depends on which module and rename the migrations as needed. I have to check all 10 modules one by one, migration by migration. Furthermore for example if I want to run everything and include the rbac migration, I have to run it manually first, and then the rest of the migrations.

Suggestion

I can execute all migrations for each module one by one or write a shell that runs commands in a specified order, but why since I have a framework? A better approach would be to have the option to run the migrate command and the command to execute the migrations in a specified order. For example by adding one new and extend an existing field of the MigrateController:

return [
    'controllerMap' => [
        'migrate' => [
            'class' => 'yii\console\controllers\MigrateController',
            'migrationPath' => [ // Might be a string or an array
                '@vendor/vendorname/yii2-user/migrations',
                '@vendor/vendorname/yii2-social/migrations',
                '@vendor/vendorname/yii2-media/migrations',
                ...
            ],
            'sortMigrations' => false, // NOTE! This will be true by default!
        ],
    ],
];

In the following case when running the command ./yii migrate --migrationPath="This will only be string". The 'sortMigrations' param will work with the 'migrationNamespaces' as well.

klimov-paul commented 7 years ago

Will not be suported - you should use MigrateController::$migrationNamespaces

traykovn commented 7 years ago

But even then, the migrations are sorted...

cebe commented 7 years ago

@traykovn migrations are sorted by the timestamp in their name. if you add migrations subsequently you automatically have the correct order. Because the tables needed by the migration you create at some point in time are already there. If you refactor your migrations or move them to modules you have to ensure timestamps are still in order. There is no point in adding another mechanism to sort migrations when we already have one.

traykovn commented 7 years ago

Ok, I see you won't take my suggestion, so there is no point to argue. I figured out how to handle my situation. Thanks!

dynasource commented 7 years ago

you can always create Migrations locally in your project with a recent timestamp and use these to override your Modules migrations.

traykovn commented 7 years ago

I just overwritten MigrateController and did what I described above. It was the simplest and the fastest solution. Thanks for your suggestion!