lenny4/doctrine-merge-persistent-collection-bundle
A Symfony bundle that provides a merge-persistent Doctrine collection, helping entities keep collection state across merges and reducing unexpected orphan removals during Doctrine entity merging operations.
Architecture fit. Despite being filed here as a Laravel/PHP package, this is a Symfony bundle (*Bundle suffix, a DI extension, and service definitions) that changes Doctrine ORM behavior. There is no Laravel service provider, no Laravel-facing config, and no Eloquent integration. On a Laravel-first stack the packaging fit is effectively zero. The domain it addresses — correctly reattaching PersistentCollection associations when merging detached entities — is a real, well-known Doctrine Unit of Work sharp edge. So the honest read is: low packaging fit, plausible domain relevance, and only if Doctrine has been deliberately introduced into the Laravel app (DDD/hexagonal boundaries, or an incremental Eloquent→Doctrine migration). From a product standpoint this is not a "PHP package we can adopt"; it is reference material for a problem we may or may not have.
Integration feasibility. In Symfony this is a trivial registration. In Laravel it is not an integration — it is a bypass. We would have to ignore the bundle layer, instantiate the underlying merge service manually, bind it in a provider, and thread it through our repository/manager code. That consumes the package's internals, not its public contract, which is the most volatile surface it has. Realistically the only defensible route is to copy or adapt the merge logic into app/Support/Doctrine/ under MIT attribution and treat upstream as a reference. Feasible in an afternoon; not feasible as a live Composer dependency in a Laravel context.
Technical risk. High, but concentrated in project health rather than code complexity:
Key questions to answer before any commitment.
merge(), orphaned children surviving an update, or a cascade-merge exception on a nested collection? If not reproducible, we do not need the package.composer.json constraints for PHP, doctrine/orm, and symfony/*, and does it install against our current versions at all?orphanRemoval, cascade: persist/merge, ordered collections (@OrderBy), composite keys, and both directions of bidirectional associations?EntityManager merges in our architecture, or is this a problem we have inherited by assumption rather than observation?Stack fit. Gate on one question first: is Doctrine ORM a sanctioned part of the stack? If the answer is "Laravel + Eloquent," close the evaluation here — the package is out of scope and there is nothing to migrate. If Doctrine is present or being introduced for a bounded context, proceed on the assumption that only the merge logic is portable and the Symfony bundle scaffolding is discarded. This is the pivotal decision point for a TPM: get it wrong and we burn a sprint integrating a package that has no business in our runtime.
Migration path. Recommend a spike-then-vendor path rather than a composer require:
EntityManager::merge().orphanRemoval handled explicitly.Compatibility. Verify three axes explicitly before any code is written: PHP minor version, doctrine/orm major (2.14+ vs 3.x), and doctrine/collections. Confirm the Symfony constraints aren't only satisfiable by Symfony 4/5 — on a modern PHP 8.2+ app that can block unrelated upgrades, because Composer resolves the whole graph even outside Symfony. Do not --ignore-platform-reqs past a conflict; that converts a dependency problem into a runtime problem and hands engineering a bug with no clean rollback.
Sequencing. Three-week bounded effort, not a quarter:
Maintenance. Treat as unmaintained-by-default. With 1 star and 0 dependents, expect no upstream fixes, no security response, and no Doctrine upgrade support. That means we own the code the moment it enters the repo: assign a named steward, register it in the dependency inventory with a review date, and attach a compatibility check to every Doctrine upgrade. The ongoing cost is modest given the small surface area, but it is non-zero and must be owned explicitly rather than assumed — this is the line item that turns a "free" MIT package into a small permanent commitment.
Support. No SLA, no vendor, no community. Troubleshooting is done by reading source. Mitigate by requiring the in-house test suite to cover the merge scenarios we depend on — that suite, not the package, becomes the actual support contract. Communicate this to stakeholders plainly: we are not buying support, we are buying a head start on edge cases and then supporting ourselves.
Scaling. Runtime cost is bounded by collection size: merging is O(n) per association and materializes whole collections in memory. On entities with large one-to-many associations this produces memory spikes and slow flush cycles. It does not scale differently from any Doctrine merge, but it concentrates cost at exactly the code path most likely to be hot in batch imports and queue consumers. Benchmark against a realistic upper-bound collection size before putting it behind a worker — the risk profile is not "it breaks," it's "it works and then falls over under load in a job nobody is watching."
Failure modes. Ranked by severity:
orphanRemoval interaction — merging triggers unintended deletes of children absent from the merged collection.Ramp-up. Low technical learning curve — a competent PHP engineer who understands Doctrine's Unit of Work can read the whole package in an afternoon. The real ramp-up is organizational: getting a decision on whether Doctrine is in scope, defining who owns the vendored code, and establishing the test coverage that substitutes for a support contract. Budget roughly one engineer-day to audit and prototype, plus test-writing around the affected entity graph. The dangerous cases — composite keys, orphanRemoval: true, ordered collections, bidirectional mappedBy/inversedBy — are where the time goes, and they are where the package's real value sits: it is a map of pitfalls, not a capability.
How can I help you explore Laravel packages today?