Migrations
Foundation migrations apply ordered database changes and record each successful run in a WordPress-backed ledger. Prefer the bundled WP-CLI command during deployment so initialization, locking, execution, and status reporting follow one path.
Create a migration
Section titled “Create a migration”Generate the database feature
Section titled “Generate the database feature”Install the generator as a development dependency:
Generate the application provider before its tables and migrations:
The generators use the project’s Composer namespace and create this feature structure by default:
When src/Database/Provider.php exists, the table and migration generators add their container registrations automatically. Register that provider in the application’s ordered provider list as shown in Database configuration.
Project-specific stubs can override the defaults at:
Define the table
Section titled “Define the table”The generated src/Database/Tables/Reports_Table.php owns its physical name and desired schema. Database::tableName() applies the current WordPress table prefix.
Apply the table definition
Section titled “Apply the table definition”The generated src/Database/Migrations/Create_Reports_Table.php passes the table object to Schema. The schema service uses dbDelta() and verifies the resulting definition before the migration is recorded as successful.
Migration IDs are permanent, byte-exact identifiers. The generator prefixes them with a sortable timestamp so migration history is easy to inspect, but execution follows provider contribution order rather than sorting by ID. Register providers and migrations in dependency order, and do not change an ID after the migration has been deployed.
For later schema changes, update the table’s desired definition and create a new migration that applies it. Use Schema::execute() for data changes or schema operations that dbDelta() cannot express reliably.
Run migrations
Section titled “Run migrations”Initialize migration storage
Section titled “Initialize migration storage”Create or reconcile Foundation’s migration ledger and lock table before running migrations:
Run this idempotent command during every deployment. Replace your-plugin with the configured command prefix; applications using the default prefix run wp nx migrate --initialize.
Apply pending migrations
Section titled “Apply pending migrations”Running the command without an operation displays migration status:
The runner acquires the configured migration lock, executes pending migrations in provider contribution order, and records each successful migration in one batch.
Roll back or rebuild
Section titled “Roll back or rebuild”Roll back the latest applied batch:
Roll back every configured migration and run them again:
Drop only Foundation’s migration ledger when intentionally resetting migration history:
Run migrations from PHP
Section titled “Run migrations from PHP”WP-CLI is the preferred deployment interface. For controlled environments that cannot invoke WP-CLI, resolve the same Migrator service from the application container:
The programmatic API follows the same ledger and lock rules as the command. Do not run migrations during every normal WordPress request.
Testing
Section titled “Testing”Use wpunit tests for table definitions, schema reconciliation, and migrations that execute against WordPress. Use integration when the test proves contributions from multiple providers, and use wpcli for the real migration command lifecycle.
Create and remove application tables within the test lifecycle so tests exercise the real wpdb and dbDelta() behavior rather than a PHP fake.