Because Flarum supports optional extension dependencies, there is a use case for optional database migrations that should only be applied if another extension is installed/enabled.
In particular, this allows achieving:
- Add column to a table created by the optional dependency extension
- Create pivot tables and foreign keys for tables created by optional dependencies
This cannot be achieved with regular migrations because there's a need for the migration to be attempted again every time an extension is enabled. And an extension cannot delete itself from the MigrationRepository (migrations
table) from within the migration since that record is only updated after the migration returns successfully.
My proposal is to add a when
callback key to migration arrays. When running up
migrations, the when
key would run first. If it exists and returns a falsy value, up
is skipped and no migration is written to the MigrationRepository. On down
migrations, everything would always run and the down
migration can simply become a no-op if it cannot find the columns/tables that it needs to delete.
I have implemented this proposal as part of flamarkt/backoffice
. The migrator changes can be found in https://github.com/flamarkt/backoffice/blob/main/src/Database/AugmentedMigrator.php while an example usage can be found in flamarkt/taxonomies
https://github.com/flamarkt/taxonomies/blob/main/migrations/20210401_000400_create_product_term_table.php
A different implementation could be to use a special exception that the up
migration could throw to cause the migration to be skipped without stopping the migrator.
Supporting down
migration so that they run when the dependency is uninstalled without running all of the extension's down
migrations is probably way too complex and I see a lot less use case for that (would only be useful when changing existing columns that must be reverted)
Are there other use cases of implementation concerns I might not have thought of?