Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Doctrine Projections Laravel Package

darangonaut/laravel-doctrine-projections

A Laravel package for Doctrine projections that helps you build and maintain read models from domain events. It integrates projection classes with Laravel’s container and console, making event-sourced read-model setup and rebuilding straightforward.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

Read-side / projection strategy (build vs. buy). This package is a build-vs-buy answer for the narrow but expensive job of turning Doctrine entity mappings into Eloquent models. In-house, that generator is a few weeks of engineering plus permanent maintenance against every Doctrine mapping edge case (single-table inheritance, mapped superclasses, self-referencing associations, composite keys). Buying it moves that maintenance burden to a dependency and lets the team spend the same time on product surface.

CQRS-lite without a rewrite. It supports the pragmatic architecture where Doctrine stays the write model and Eloquent powers the read model — admin panels, reporting screens, API resources, paginate/cursor/chunk, route model binding, toArray/toJson, replicate. That is a decision to not migrate the write side, which is usually a much larger roadmap item. Product-wise this unlocks read features (search, list views, exports) on a Doctrine codebase without a doctrine-to-Eloquent migration epic.

Phasing a Doctrine exit (or not committing to one). Teams that want to leave Doctrine eventually can move read paths first, ship user-visible value, and defer the risky write-path migration indefinitely. This package makes "migrate later, incrementally" a defensible roadmap position rather than a vague intention.

Event-sourced / derived read models. Generation is mapping-driven and requires no database — 200 entities in 0.03s, pinned by a test. That makes projection generation a cheap, deterministic step in CI and a viable fit for event-sourcing read models that must be rebuildable from scratch. A PM can treat regenerating the read side as a routine, low-cost operation rather than a maintenance window.

Correctness and release-confidence decisions this release informs. Three items in v0.7.0 are product-risk items, not just engineering ones:

Release-note item Product consequence
Abstract mid-hierarchy class returned every row (unscoped) Read models could over-report — e.g. a "files" list silently including folders. User-visible wrong data, not a crash.
Failed write reported as "success", exit 0 Deploys could go green with zero models generated. This is a supply-chain-style failure mode: no alert, silent outage of read features.
Three inputs now refused instead of silently allowed Namespace collisions, case-only filename collisions (macOS/Windows), and migration overwrites were previously resolved by whichever file won. Now they fail loudly.

That last row is the most PM-relevant: the failures were moved from runtime/data-corruption into build time. It is a quality-direction signal worth citing when justifying the dependency, and worth citing against complacency if the team was previously relying on the silent behaviour.

Roadmap input — version risk. At v0.7.0 this is pre-1.0 and the release notes are explicit that a minor was effectively breaking: three things that used to run now refuse. For roadmap planning that means: pin the version, budget a small upgrade task per minor bump, and read UPGRADING.md as part of the upgrade ticket. Do not place this on a critical path where an unreviewed bump can ship.

When to Consider This Package

Adopt when:

  • You have a Doctrine ORM codebase and a genuine need for Eloquent-shaped read models — Laravel-native list/detail screens, API resources, admin tooling, reporting, exports.
  • Doctrine must stay as the write model for now, or permanently, and a full migration is not funded.
  • Your mapping uses inheritance hierarchies (single-table especially), mapped superclasses, self-referencing associations, or composite keys — the release notes show these are the tested, hard-won paths, and precisely where a homemade generator tends to be wrong quietly.
  • You want projection generation in CI with no database available.
  • Your runtime is in the supported matrix: PHP 8.3/8.4, Laravel 12/13, SQLite / MySQL 8.4 / PostgreSQL 16. 211 tests, PHPStan level max with no baseline, is a reasonable proxy for maintainability.
  • You can tolerate pre-1.0 churn: pinned versions, an upgrade task per minor, and a read of UPGRADING.md before bumping.

Look elsewhere when:

  • There is no Doctrine footprint. The package's entire value is reading Doctrine mapping; with a pure Eloquent or pure Doctrine codebase it is dead weight.
  • You need write-side support or bidirectional sync. This is a projection generator, not a persistence bridge.
  • The team cannot absorb breaking changes in minor releases. Pre-1.0 semver means the v0.7.0 pattern — a "minor, not a patch" that refuses inputs previously accepted — is likely to recur. If your release train cannot accommodate that, wait for 1.0 or wrap it behind an internal generator interface.
  • Your mappings are already known-broken. Non-backed enums, enumType on a json column, and a discriminator column mapped as a field are documented, not guarded. Those are yours to fix first; the package will not protect you from them.
  • You need a vendor with an SLA or commercial support. Nothing here indicates that.
  • You have very few entities (single digits) and no inheritance — the payoff over hand-written Eloquent models is small, and the dependency-plus-upgrade cost may exceed the saving.

How to Pitch It (Stakeholders)

To executives: This is an infrastructure dependency that lets us ship read-facing features — admin screens, reporting, API resources, search and export views — on a Doctrine codebase without funding a full persistence migration. It replaces an in-house generator we would otherwise own forever, and it removes a class of silent bugs: in the previous release, a failed code-generation step reported success and exited cleanly, so a deploy could go green while read features were missing. The new version fails loudly instead. It is pre-1.0 and generates a small upgrade task per minor release; we pin the version and review the upgrade notes, which is normal for developer tooling at this stage. Cost is a dependency plus a few hours per upgrade; the alternative is weeks of build and permanent maintenance.

To engineering: v0.7.0 is a minor that behaves like a breaking change — three previously-accepted inputs now refuse: a projection namespace colliding with your entity namespaces, two entities whose short names differ only in case (one file on macOS/Windows), and overwriting an existing migration (the timestamp-to-the-second plus a default doctrine_diff name made same-second collisions likely). All three are in UPGRADING.md and all three convert silent corruption into a build failure, which is the right trade. Two real fixes shipped: an abstract class mid-hierarchy had no scope and returned every row in the table (now scoped below the root), and File::put() returning false or throwing ErrorException was previously unchecked, so a no-op run printed "3 projection(s) generated" and exited 0. Generation requires no database and is now test-pinned — 200 entities in 0.03s — so it belongs in CI. Verified unchanged and worth knowing is covered: self-referencing OneToOne/ManyToMany, two associations onto one entity, mapped superclasses, key-only entities, indexBy on a self-reference, fetch/cascade/orphanRemoval, nullable composite-key columns, and the Eloquent surface we actually use — chunk, cursor, lazy, paginate, route model binding, replicate, toArray, toJson — all under Model::shouldBeStrict(). Green on PHP 8.3/8.4 × Laravel 12/13 across SQLite, MySQL 8.4 and PostgreSQL 16, PHPStan level max with no baseline. Pin the version, put the upgrade in the ticket.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log