dualmedia/disable-orm-bundle
A Symfony + Doctrine bundle that lets you transparently disable entity fields from the ORM via a #[DisableORM] attribute, enabling zero-downtime deployments and safe field removal across multiple app versions.
doctrine.orm.entity_managers.<name>.class_metadata_factory_name, ships Symfony bundle registration (config/bundles.php), and has no Eloquent equivalent. A Laravel-only roadmap gets zero value from it; a Symfony/Doctrine service gets a narrow but real capability. Confirm stack before anything else — this is the cheapest and most important call.#[DisableORM], ship the release that ignores it, then drop the column in a follow-up migration. Old and new instances can run against the same database during a rolling deploy. This converts a synchronized all-hands migration event into two ordinary deploys — a release-engineering capability, not a feature.ClassMetadataFactory override plus an attribute — plausibly a few hundred lines in-house. The differentiators worth paying attention to are the guardrails: a configurable disable_on_commands allowlist (defaults keep doctrine:schema:validate and doctrine:migrations:diff seeing the field so migrations can still target it), a PHPStan rule for entity misuse, and a CI git-diff script that fails builds when a field is deleted without first being #[DisableORM]-flagged. That CI check is arguably the real product — it prevents the one mistake that would otherwise turn this into an outage generator.Adopt when all of these hold:
EntityManager.class_metadata_factory_name per entity manager, and wire the PHPStan include plus the CI change-detection script into the pipeline.SELECT *-style query builders, hydrators, and any admin/API layer (EasyAdmin, API Platform, Gedmo/Stof-style extensions) that introspects mappings.Look elsewhere — or don't adopt — when:
Risk notes for the decision record: disabled fields vanish from ORM introspection, so failures surface as wrong query results or missing-property exceptions rather than loud errors; setup is manual YAML, so config drift is real; and "re-enable" rollback means removing the attribute and redeploying — fine, but not instant.
For executives (one paragraph): "We run several versions of the app at once during deploys, which today means either a maintenance window or a risky all-at-once migration whenever we want to drop a database column. This is a small MIT-licensed Symfony add-on that lets a new version ignore a column while the old version keeps using it — so retiring a column becomes two ordinary deploys instead of one coordinated, downtime-inducing event. Think of it as a feature flag for our database schema. The cost is near zero, the code footprint is tiny, and it ships with a static-analysis rule and a CI check that block the one dangerous misuse — deleting a field without flagging it first. The caveats: it's a single-maintainer, zero-adoption open-source project, so I'd want to pilot on one service and accept that we may end up owning a fork; and it's Symfony-only, so it does nothing for our Laravel services."
For engineering (the ask): "Add dualmedia/disable-orm-bundle, register DualMedia\DisableORMBundle\DisableORMBundle in config/bundles.php, and set class_metadata_factory_name: DualMedia\DisableORMBundle\Factory on the entity manager. Keep the default disable_on_commands list so doctrine:schema:validate and doctrine:migrations:diff still see the field. The workflow is: ensure the column has a DB default, tag the property #[DisableORM], deploy, then drop the column in a follow-up migration. Add the extension.neon PHPStan include and the /scripts git change-detection job to CI so a field can't be deleted without having been flagged first. Pilot on one low-traffic entity, verify repository/query-builder/hydration behavior and any metadata-consuming bundle, then roll out. Keep a one-line runbook: 'Column missing or query returning fewer fields? Check whether the property is #[DisableORM]-tagged.'"
Sequencing for the delivery lead: pilot on non-critical entities → validate queries and admin/API layers → add the PHPStan and CI gates → then make it the standard path for column removals, with @deprecated annotations as the on-ramp.
How can I help you explore Laravel packages today?