Database Migrations
debt(d7/e5/b7/t5)
Closest to 'only careful code review or runtime testing' (d7). The tools listed (phinx, doctrine-migrations, laravel-migrations) manage migrations but don't automatically detect when someone bypasses them with direct ALTER TABLE statements. Detection requires manual code review or process audits to ensure all schema changes go through migration files. The detection_hints explicitly state automated detection is 'no'.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix says 'every schema change must be a reversible migration file' — retroactively creating migrations for manual changes requires examining production schema, creating migration files, potentially writing down() methods, and testing rollback paths. For accumulated manual changes, this spans multiple migration files and database state reconciliation.
Closest to 'strong gravitational pull' (b7). Database migrations apply across all contexts (web, cli) and fundamentally shape how teams deploy and coordinate. Once a project establishes a migration workflow (or lacks one), every future schema change and every developer is affected. The choice of migration tool and conventions becomes load-bearing infrastructure that every database-touching feature must respect.
Closest to 'notable trap' (t5). The misconception field explicitly states developers wrongly believe 'migrations are only needed for schema changes' when they should also cover data transformations, seed corrections, and index changes. This is a documented gotcha that most developers eventually learn, but the initial mental model of 'migrations = CREATE/ALTER TABLE only' leads to inconsistent database states across environments.
Also Known As
TL;DR
Explanation
Database migrations track schema changes as numbered, ordered scripts checked into version control alongside application code. Each migration has an up (apply) and down (rollback) operation. Migration tools for PHP include Doctrine Migrations, Phinx, and Laravel Migrations. Migrations must be backward compatible during blue/green or canary deployments — the old code must work with the new schema until deployment completes. Best practices: one change per migration, never modify a committed migration (add a new one), include data migrations where schema changes require data backfill, and run migrations atomically in a transaction where the database supports it.
Common Misconception
Why It Matters
Common Mistakes
- Running ALTER TABLE directly on production without a migration — the change is not reproducible.
- Migrations that lock the table on large datasets — use online schema change tools for big tables.
- Irreversible migrations with no down() method — prevents rollback if the deploy fails.
- Multiple developers running conflicting migrations simultaneously — use sequence numbers or timestamps.
Code Examples
// Schema change run directly on production — not tracked:
mysql -u root -p production_db -e "ALTER TABLE users ADD COLUMN phone VARCHAR(20)";
// Not in version control, not reproducible, team doesn't know it happened
// Migration:
public function up(): void {
Schema::table('users', fn($t) => $t->string('phone', 20)->nullable());
}
// Phinx migration — up() and down() must be inverse operations
class AddStatusToOrders extends AbstractMigration {
public function up(): void {
$this->table('orders')
->addColumn('status', 'string', [
'limit' => 20,
'default' => 'pending',
'after' => 'total',
])
->addIndex('status')
->save();
}
public function down(): void {
$this->table('orders')
->removeColumn('status')
->save();
}
}