What is the best way to handle Events that get triggered during a migration?
In general it’s best to avoid calling service methods from migration files in the first place. The reason for that is, your services should be able to assume that they’re always working with the latest schema design.

Imagine if a month from now you decide you need to add a new column to your formentries table (or whatever it is). The associated record, model, and service all get updated to work with this new column’s data. And you write a migration that adds the column:

$this-&gt;addColumn('formentries', 'newColumnName', ColumnType::Varchar);


You test and everything appears to work great, and then release it.

Then someone who was running an old version of your plugin tries to update. Before Craft runs the new migration that adds the new formentries column, it still needs to run your old migration that calls your saveFormEntry() service method. Except that saveFormEntry is now assuming that the new column already exists, and depending on your code, either they run into a validation error (so no form entries get saved) or a MySQL error (because your record is trying to save on a column that doesn’t exist yet).

So, in the long run you’ll be better off if you keep all DB-related changes contained to your migration file.

That said, Craft does cheat a little here - this is exactly why we have the concept of “breakpoint updates” at our disposal. When we mark a release as a breakpoint, it prevents anyone from updating to a version after it, until they have updated to it. So if we do need to call service methods in a migration, then we just need to remember to set a breakpoint at some point before we start making more DB schema changes.

Plugins will also be able to set breakpoints when Craft 3 comes along. Because of that, this is still a relevant question. I’m thinking that the safest thing to do here is to simply disable event dispatching altogether during updates. A plugin should be in full control over what code gets run when it’s updating itself, with no chance of another plugin intervening.

I don’t think we have a way to disable Yii’s event system altogether (and probably shouldn’t even if we could), but we could at the very least prevent craft()->on() from doing its thing during update requests. Maybe even add a new argument to it that can be set to true if the event should get fired even if it’s an update request, in case there are any use cases that I’m overlooking.