Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.8] Migration Events #28342

Merged
merged 11 commits into from
May 2, 2019
Merged

[5.8] Migration Events #28342

merged 11 commits into from
May 2, 2019

Conversation

alexbowers
Copy link
Contributor

This PR adds events to migrations.

Events added:

migrations.beforeAll:up
migrations.afterAll:up
migrations.beforeAll:down
migrations.afterAll:down
migrations.before:up
migrations.after:up
migrations.before:down
migrations.after:down

The benefit of having these methods is it will allow users to clear cache on migrations, perform maintainence if necessary.

The before:up, before:down, after:up and after:down methods all receive the migration that was ran as a parameter, so that you can check which migration you are running to see if you need to perform any specific action.

Fixes laravel/ideas#854

Copy link
Member

@driesvints driesvints left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're on the right track but I believe we can do better. First of all: there's no need for the static keyword anywhere. Check my comments.

I also believe it might be better if we used dedicated classes instead of the string based ones. There's an Illuminate\Database\Events where you can add these.

Based on your list above these could be:

  • UpMigrationsStarted
  • UpMigrationsEnded
  • DownMigrationsStarted
  • DownMigrationsEnded
  • UpMigrationStarted
  • UpMigrationEnded
  • DownMigrationStarted
  • DownMigrationEnded

And might I suggest adding:

  • MigrationsStarted
  • MigrationsEnded
  • MigrationStarted
  • MigrationEnded

Maybe we only need the last four above? Do we really need to know if a migration is a down migration or not?

Nice job so far 👍

src/Illuminate/Database/Migrations/Migrator.php Outdated Show resolved Hide resolved
src/Illuminate/Database/Migrations/Migrator.php Outdated Show resolved Hide resolved
src/Illuminate/Database/Migrations/Migrator.php Outdated Show resolved Hide resolved
src/Illuminate/Database/Migrations/Migrator.php Outdated Show resolved Hide resolved
src/Illuminate/Database/Migrations/Migrator.php Outdated Show resolved Hide resolved
@alexbowers
Copy link
Contributor Author

@driesvints I have made those changes. Couple of things to note.

For the events, in the old system there was wildcard support, which is why I have put a Contract in there, since that allows the same thing:

Events::listen(\Illuminate\Contracts\Database\MigrationEvent::class, ...);

I have also changed how data is passed around, the events now instead store the migration and the direction, instead of it being a separate parameter.

Copy link
Member

@driesvints driesvints left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job man. Just a few small things and the StyleCI failures.

src/Illuminate/Database/Events/MigrationEvent.php Outdated Show resolved Hide resolved
src/Illuminate/Database/Migrations/Migrator.php Outdated Show resolved Hide resolved
src/Illuminate/Database/Migrations/Migrator.php Outdated Show resolved Hide resolved
src/Illuminate/Database/Migrations/Migrator.php Outdated Show resolved Hide resolved
Copy link
Member

@driesvints driesvints left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more things. Also: this PR could also use some tests.

src/Illuminate/Contracts/Database/MigrationEvent.php Outdated Show resolved Hide resolved
src/Illuminate/Database/Migrations/Migrator.php Outdated Show resolved Hide resolved
@deleugpn
Copy link
Contributor

deleugpn commented Apr 26, 2019

I would like this as well. I have some migrations that change information inside the database and I wanted to write tests to make sure the migration was doing the expected process, I ended up doing this:

    private function afterMigration(string $migrationName, callable $callback)
    {
        DB::listen(function (QueryExecuted $query) use ($migrationName, $callback) {
            if (isset($query->bindings[0]) && $query->bindings[0] === $migrationName) {
                $callback();
            }
        });
    }


    private function migrate()
    {
        $this->afterMigration('2018_11_14_154917_some_migration', function () {
            // Add some seed data at this point before changing the database format
        });

        Artisan::call('migrate');
    }

@alexbowers
Copy link
Contributor Author

@driesvints I have done the above, but I was having some trouble with the tests. Not sure why, but Event:assertDispatched was not working for me.

Any advice? As it stands, it basically is fine if it has assertions.

Not ideal, but it does test it.

Copy link
Member

@driesvints driesvints left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any advice? As it stands, it basically is fine if it has assertions.

Current assertions are fine 👍

I see you've added a merge commit. Can you try to purge this commit and use rebase instead? Because this adds unnecessary extra commits to the PR.

tests/Integration/Database/MigrateWithRealpathTest.php Outdated Show resolved Hide resolved
src/Illuminate/Database/Migrations/Migrator.php Outdated Show resolved Hide resolved
@alexbowers
Copy link
Contributor Author

@driesvints I can try to collapse the commits down. Do you want me to just squash them all?

@alexbowers
Copy link
Contributor Author

@driesvints I haven't been able to get the merge commit fixed. Any chance when this is merged it just gets squashed instead? Or can you help me with fixing the merge commit? Either or is fine by me :D

Copy link
Member

@driesvints driesvints left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost there.

src/Illuminate/Database/Migrations/Migrator.php Outdated Show resolved Hide resolved
@driesvints
Copy link
Member

@alexbowers squashing can't be done anymore because you're used merged commits. If you want to fix this you'll need to start a new branch from 5.8 and cherry pick your commits on top. You've used multiple merge commits atm.

@alexbowers
Copy link
Contributor Author

Ok i'll figure it out this evening. Might have to be a new PR or a force push or something.

@driesvints
Copy link
Member

@alexbowers should be able to do it with a force push. Don't need to open up a new pr. Don't forget to backup your branch first to prevent losing stuff.

@alexbowers
Copy link
Contributor Author

Ok @driesvints I think thats worked.

Copy link
Member

@driesvints driesvints left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job 👍

@alexbowers
Copy link
Contributor Author

Any more changes, or are you good with this?

@driesvints
Copy link
Member

@alexbowers see the approval above :)

@driesvints
Copy link
Member

You could perhaps squash your commits.

@alexbowers
Copy link
Contributor Author

Ah missed that. It should be able to be squashed by the merger, since if I was to squash now that'd be another force push. I'd rather avoid that just incase I bin it :D

@devcircus
Copy link
Contributor

Just a thought, but in Illuminate/Auth/Events the namespace delineates the classes within as events. The classes themselves are "Login", "Logout". etc. So Illuminate/Contracts/Database/Events/Migration makes sense in that context.

@driesvints
Copy link
Member

@devcircus right. Let's just leave it at this.

@ttomdewit
Copy link

Thanks for everyone's hard work this past week, hopefully it'll be considered and merged. 👍

@taylorotwell taylorotwell merged commit 3dd96ad into laravel:5.8 May 2, 2019
@alexbowers alexbowers deleted the feature/migration-events branch May 2, 2019 20:29
@jasonmccreary
Copy link
Contributor

Were these added to the docs anywhere? Glad to do it. Just didn't want to duplicate work.

@driesvints
Copy link
Member

@jasonmccreary I don't think they were.

@wouterrutgers
Copy link
Contributor

Was it intended that no events will be executed if there are no migrations available? (See: https://github.com/laravel/framework/blob/5.8/src/Illuminate/Database/Migrations/Migrator.php#L141)

A use case for where it would be useful to always send the events:

We have our own migrator which will run a migration multiply times with different variables given to the migration. We run this migrator on the MigrationsEnded event. When we have no default migrations but only custom migrations the event is never executed. Therefor our custom migrations are never ran.

@ttomdewit
Copy link

@wouter2203 Personally I’ve never thought about that particular requirement.

@wouterrutgers
Copy link
Contributor

wouterrutgers commented Aug 2, 2019

We were just calling another command after php artisan migrate that would run our own migrations. Then we read somewhere (laravel-news I think) that migration events were available, so we deleted that command and used the events. Only to notice that our custom migrations were not always running..

Would be cool if we get some extra events, something in the lines of Starting, Running, Ended. Where Running would just never be fired when no migrations are available.

@driesvints
Copy link
Member

@wouter2203 you're always free to send in a follow-up pr. Make sure to thoroughly describe your use-case.

@ArlonAntonius
Copy link

I don't know @wouter2203's exact use case, but I actually need something among the same lines and was wondering if you guys would be open to the following:

Would love to hear your feedback on this as well @wouter2203 would it help with your use case or would you also need the Running Event?

@driesvints
Copy link
Member

@ArlonAntonius that sounds reasonable. Let's wait to see what @wouter2203 thinks.

@wouterrutgers
Copy link
Contributor

@ArlonAntonius If the Ended event is also fired when no migrations are ran it'll work for my use case. The normal migrations should run before the custom migrations, so we need to listen for Ended. And in that case the Ended migration would just contain an empty array.

To elaborate on (one of) my use case(s):

Let's say we have a multilingual cms system where users can manage the mailings that are send by that system. When a new mailing is added we'll make a custom migration that'll run the following:

    public function up($locale)
    {
        Mailing::create([
            'locale' => $locale,
            'template' => 'A new mailing',
        ]);
    }

To have the above work we need the normal migrations to be ran first, otherwise the mailings table would not exist.

Now if we have configured ['en', 'nl', 'de'] as locales for that cms the above is executed 3 times, each time with a different $locale.

Ofcourse the mailing would be added with an English template for all 3 locales, but now the user can edit the template for nl and de in the cms.

I can create a pull request in which the Starting and Ended events are implemented, If you agree with both the Starting and Ended events always firing.

@ArlonAntonius
Copy link

@wouter2203 Sounds good to me should be enough to fix my actual use case, please mention me @ the PR so I can double-check.

@ttomdewit
Copy link

Thanks for taking this to the next level.

@gasparyanm
Copy link

gasparyanm commented May 12, 2020

Laravel Migration event listeners don't work in my case.

namespace App\Providers;

use App\Listeners\DeleteUnitsAwsImages;
use Illuminate\Database\Events\MigrationsStarted;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        MigrationsStarted::class => [
            DeleteUnitsAwsImages::class,
        ]
    ];
....

@alexbowers
Copy link
Contributor Author

Please can you open an issue if you think this is a bug

@gasparyanm
Copy link

gasparyanm commented May 12, 2020

Please can you open an issue if you think this is a bug

I opened the discussion, as I need something like support or additional info related to doc
Please see here #32778 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fire events on migrations