stemble/laravel-doctrine-factory
Use Laravel's modern Eloquent factories with Doctrine entities. Drop-in replacement for the official frozen pre-8.x factory system, adding class-based factories, first-class states, relationship helpers, sequences, recycle, and afterMaking/afterCreating callbacks.
$factory->define() system shipped with laravel-doctrine/orm. That is a developer-experience and hiring decision as much as a technical one: the modern API is what most Laravel engineers already know.EntityManager. This package is MIT, ~one file of integration surface, and extends Illuminate\...\Factory rather than replacing it — which meaningfully lowers the cost of trying it and the cost of removing it.for(), has(), magic hasPosts()/forUser(), sequence(), recycle(), and named state methods (->admin()) are what turn 40-line fixture setup blocks into one-liners. If fixture boilerplate is a recurring complaint in retros, this is a concrete, low-risk lever.make() calls persist() and bidirectional inverse sides aren't synced in memory — is the entire delta your team must learn.hasAttached() (many-to-many with pivot data) requires working through a pivot entity. If your test plan assumed Eloquent parity there, that scope needs re-planning now rather than mid-sprint.Adopt when all of the following hold:
laravel-doctrine/orm's official factory system, or writing fixtures by hand, and feel that pain.make() a whole graph and flush() once, with no cascade: ['persist'] annotations needed.Look elsewhere or hold off when:
afterMaking()), but it's a correctness hazard, not a convenience gap.make()-persists-to-the-identity-map deviation is the kind of thing that produces "why did my test insert rows?" bugs. Mitigable with a lint rule or convention, but it needs a decision, not a default.For executives — one paragraph: Our tests for the Doctrine-backed parts of the application currently use a factory system frozen at a Laravel API that was deprecated several major versions ago. This package is a small, MIT-licensed adapter that lets those tests use Laravel's current factory API — the same one our engineers already use everywhere else. It costs essentially nothing to evaluate, is removable without touching application code, and the payoff is faster, more readable test setup and no Doctrine-specific training burden for new hires. The honest risk is that it is a very young package with no external adopters, so I recommend a time-boxed evaluation on one bounded area of the test suite before wider rollout.
For engineering — the substance:
HasFactory trait to the entity, extend DoctrineFactory, mirror your entity namespace under database/factories/. No Doctrine-specific trait to import, no changes to Illuminate\...\Factory.for()/has()/magic relationship helpers, sequences, recycle(), and afterMaking()/afterCreating().make() calls EntityManager::persist() — it registers in the identity map. Any later flush() inserts it. This is deliberate and it's what lets you build a graph then flush once, without cascade annotations.afterMaking().configure() via afterMaking(); otherwise $user->getPosts() is empty until flush-and-refresh. This is the biggest trap for anyone arriving from Eloquent.for()/has() take the entity property name, not a column or class name. Magic methods infer it when the property name matches the related class basename.trashed()), and hasAttached() — M2M with pivot data goes through the pivot entity.Recommendation: treat this as a spike, not a commitment. Evaluate on one bounded test area, judge it on three things — does the test suite catch the make()/flush() interaction, do our entity setters carry logic that reflection would skip, and does the maintainer respond to issues — and only then decide. The upside is real developer velocity; the downside is bounded because the package sits entirely in test tooling and costs one composer remove to undo.
How can I help you explore Laravel packages today?