Hello,
I would like to share the way we have implemented database migrations.
We have implemented data migrations and batch accounting the Laravel way:
1. A special controller for DevelopmentAdmin that handles request:
/dev/db – Lists pending and last batch migrations.
/dev/db/migrate_data – migrates the data.
2. All files with migration classes must be of form YYYYMMDD_HHMM_ClassName.php and extend default SS MigrationTask class.
3. We keep all migrations in one folder, but they may be anywhere. SS class manifest is used to collect all the classes that extend MigrationTask.
4. The migration class may implement 3 methods: prepare, up, down, but only up() is mandatory.
5. The deployment runs like this:
a) Copy files
b) sake dev/db/migrate_data –prepare
Create backups or manipulate existing db data with old db schema
c) sake dev/build
Update db schema
d) sake dev/db/migrate_data
Run data migration tasks. This automatically creates a new batch of the tasks.
If some error happened during lasts step, we call
sake dev/db/migrate_data --rollback
and continue with standard rollback sequence.
During development you can run a separate task as standard build task: sake dev/tasks/MyMigrationTask
Cons: we cannot call prepare() or down() methods with existing MigrarionTask class, the logic of run() method should be changed.
Gregory
No, you should not disable /dev/build since they complement each other.
Imagine you have new ImprovedProduct class and need to migrate old data from Product.
dev/build
1. Updates database schema: creates new ImprovedProduct table.
2. Does data seeding by calling DataObject::requireDefaultRecords()
dev/db/migrate_data
1. Moves/transforms data from table Product into ImprovedProduct
2. Renames Product table into _obsolete_Product
Infrastructure ensures that such migration is run only once.
The benefits we got:
- Method requireDefaultRecords() now has one responsibility: data seeding (we used to put small migration logic there)
- No need to keep a list of extra changes to do after deployment (we used to create BuildTasks to do migrations manually)
- We have a clean history of code and data changes in the repository.