doctrine/migrations
Doctrine Migrations is a database schema migration library for PHP, letting you version and track schema changes with a robust CLI and API. It integrates with Doctrine DBAL and ORM to safely apply, roll back, and manage migrations across your projects.
scripts/migrate.php plus a schema_versions table) is a 2–4 week engineering detour that re-implements rollback ordering, partial-failure recovery, and drift detection badly. Default decision: buy (free), and spend the saved effort on migration review process instead of migration plumbing.doctrine/migrations is only on the table if the team is already using Doctrine ORM/DBAL (typically via laravel-doctrine/orm or in a Symfony/shared-domain context). If the product is a conventional Eloquent app, this package is not a decision — it's a distraction. If a bounded context needs rich mapping (inheritance, embeddables, composite keys, second-level cache), Doctrine plus this migration library becomes the coherent pairing, and that becomes an architecture recommendation rather than a tooling one.migrate, migrate --dry-run, status, diff, and rollback surface maps directly onto a CI/CD gate: fail the pipeline on un-run migrations, generate a reviewable SQL diff in the PR, and block deploys when the migration set is non-deterministic. This is a process decision (do we gate on migrations?) that the package makes cheap to answer yes to.preUp/postUp/preDown/postDown hooks, so backfills, re-keying, and denormalization cleanups live in the same versioned, ordered, auditable stream as schema changes. PMs can commit to "every data transformation is reviewed, ordered, and reversible" as a product-quality guarantee rather than a best-effort convention.doctrine/dbal 4.5 deprecation fix and a Dependabot actions/checkout bump. That signals a maintenance-mode dependency with a low feature-velocity surface. Planning implication: budget a pin-and-bump cadence (track the 3.9.x patch line, evaluate 4.0.x deliberately) rather than expecting capability gains from upgrades. The 3.9.8 example is the cadence working as intended: a deprecation fix that keeps you current on DBAL, not a feature you plan around.Adopt when most of the following hold:
Look elsewhere when:
artisan, testing, and RefreshDatabase. Introducing Doctrine plus this package for migration purposes alone is pure carrying cost. This is the single most common misapplication of this package in a Laravel context.Two adoption notes worth surfacing to engineering: the README is a stub and all real documentation lives off-repo at doctrine-project.org, so onboarding cost is real and should be scheduled; and the "Dependents: 0" figure in the metadata is a measurement artifact, not evidence of low adoption — the package is pulled in transitively by DoctrineBundle and the wider Doctrine stack. Treat the 4.7k stars, the steady patch cadence (3.9.8 is a routine two-PR bugfix release), and the Doctrine core team's ownership (greg0ire, derrabus, morozov) as the real adoption signal. Practical bump guidance from 3.9.8: if you are on DBAL 4.5+, take this patch to clear deprecation noise — but no code or configuration change is required, so it needs no release window of its own.
To executives: Database changes are the highest-blast-radius step in any deploy — the failure mode isn't a bad page, it's corrupted or unrecoverable data. Doctrine Migrations is a free, MIT-licensed, decade-old library from the Doctrine project that turns schema changes into versioned, ordered, reviewable, revertible artifacts. We don't pay for it, we don't maintain it, and we don't have to build it. Adopting it lets us make a concrete commitment to auditors and enterprise buyers: every schema change is recorded, ordered, and reversible. The cost is a one-time integration and a team convention; the alternative is a bespoke script that we own forever and that nobody wants to be on-call for.
To engineering: This is the boring, correct choice for schema management in a Doctrine context. You get diff-generated migrations from your mapping, an all-or-nothing transactional mode, --dry-run and status for CI gating, pre/post hooks for data backfills, and multi-entity-manager support for per-tenant schemas. It runs on Symfony Console, so it's scriptable and testable, and you can invoke the migration API from application code instead of shelling out. Caveats we should agree on up front: the on-repo README is a pointer, so real documentation is external — budget a day of onboarding; the project is in maintenance cadence (the latest release, 3.9.8, is a DBAL 4.5 deprecation fix plus a CI action bump — no features, no breaks), so we pin to the 3.9.x patch line and treat 4.0.x as a planned, separate evaluation; and it will happily run a migration that locks a 40M-row table, so we pair it with a destructive-change review rule. Important scoping note: for a plain Eloquent Laravel service, we should not adopt this — Laravel's native migrations already cover us, and adding Doctrine purely for migrations is cost with no payoff. This recommendation applies specifically to our Doctrine-backed services.
How can I help you explore Laravel packages today?