lmc/cqrs-handler
Laravel CQRS handler package that simplifies command and query buses with automatic handler resolution, dependency injection, and clean separation of write and read logic. Ideal for structuring growing applications with maintainable, testable business actions.
Architecture fit. Unchanged in substance: the package remains a base implementation for CQRS types — contracts and thin abstractions for commands, queries, and handlers, not a framework. 2.3.0 reinforces that positioning rather than altering it. The addition of Symfony 8 support is a useful signal: the maintainers are deliberately keeping the package framework-agnostic and are investing in a second integration surface. That is consistent with our read of it as a convention layer, and it slightly improves the odds that the abstractions are genuinely portable rather than Laravel-shaped by accident. It does not give us a Laravel service provider, handler discovery, or bus implementation — we still own all of that. Value remains concentrated on the query side and on enforcing a consistent cross-module vocabulary.
Integration feasibility. Mechanically unchanged: composer require, implement interfaces on DTOs, write handler classes, add a small adapter resolving handlers from Laravel's container. Still ~1–3 engineer-days for a proof of concept. One new feasibility check is now mandatory before we commit: does 2.3.0's Symfony 8 support change the package's PHP floor or pull Symfony components as hard dependencies? Symfony 8 targets PHP 8.4, so a careless require (rather than require-dev/suggest) could force our runtime PHP version up or drag in symfony/* packages we don't want alongside Laravel. Verify composer.json constraints and run composer why symfony/console (or equivalent) in the spike. If Symfony support is correctly optional, integration cost is unchanged; if not, it's a blocker for Laravel 10/11 shops on PHP 8.1–8.3.
Technical risk. Still high on adoption signals, but marginally improved:
php constraint.Key questions.
symfony/* a hard or optional dependency in 2.3.0, and did the Symfony 8 work raise the minimum PHP version?^7.0|^8.0 vs ^8.0)? A hard ^8.0 would drop compatibility with older Symfony and signal a willingness to take hard major-version stances in minor releases.Stack fit. Laravel 10/11/12 on PHP 8.1+ remains the target. 2.3.0 confirms the package will not fight Laravel's container, service provider, or queue system — and equally confirms it will not use them for us. The Symfony 8 work is a mild positive for portability but delivers nothing to a Laravel codebase directly. The Illuminate\Bus collision still needs an up-front decision: keep Laravel's dispatcher for queued/side-effect commands, use this package for the query path and CQRS contract enforcement in new modules.
Migration path. Unchanged and still the right call: greenfield modules only, behind our own App\CQRS\CommandBus / App\CQRS\QueryBus interfaces. 2.3.0 slightly strengthens the case for this adapter — a package with a Symfony integration surface is more likely to evolve its abstractions in ways that serve Symfony first. Our internal interface keeps that evolution from reaching our domain code.
Compatibility. Add to the previous checklist: audit composer.json for Symfony constraints and php constraint changes between the version we evaluated and 2.3.0; diff the two releases if a changelog is thin. Confirm no transitive dependencies are pulled in. We still own container wiring and handler registration; prefer an explicit handler map (or attribute discovery) over convention-over-magic so failures are loud and static analysis can trace command→handler.
Sequencing.
~2.3. If it is stub-level, undocumented, or drags in a PHP/Symfony constraint we can't accept, vendor the ~200 lines under our namespace and skip the dependency.~2.3 with lockfile discipline, no floating ranges).Version note. We evaluated pre-2.3; if the spike proceeds, target 2.3.0 specifically and record it in the ADR. Do not float across the Symfony-constraint change without re-reading composer.json.
Maintenance. Low code volume; we still absorb 100% of glue code and convention drift. Budget ~1 day/quarter for PHP/Laravel upgrade compatibility checks and pin the exact version. 2.3.0 modestly improves the maintenance outlook — a release that tracks upstream framework versions suggests someone is watching the ecosystem. It does, however, add one more axis we must monitor: the package's Symfony and PHP constraints can move independently of Laravel's, so a routine composer update could surface a conflict originating upstream. Keep the lockfile pinned and update deliberately.
Support. No vendor SLA, no commercial backing, community issues only on a low-visibility repo. Effective support model remains internal ownership: name a maintainer, record the fork/vendor contingency in the ADR. The 2.3.0 release is a point-in-time signal, not a support commitment — do not let it lull the team into treating the package as externally maintained.
Scaling. Unchanged. In-process dispatch; the library is not a scaling factor. Synchronous handlers keep latency predictable but couple request time to handler work. Anything slow or I/O-heavy goes through Laravel's queue, which this package does not abstract. Keep handlers small, push heavy work to jobs, and watch for handler bloat and hidden N+1s in query handlers once teams get comfortable.
Failure modes.
composer update; mitigated by pinning and by reviewing composer.json diffs on every bump.Illuminate\Bus vs. this) causing confusion about where middleware and transactions apply.Ramp-up. Low technical ramp — a Laravel developer grasps command/handler in under a day. The real ramp is convention: where validation lives, what a handler may return, when to queue, how queries differ from Eloquent scopes. Documentation is likely still thin, and the Symfony-facing release notes tell us nothing about Laravel usage, so invest in a short internal README plus one reference module. Expect ~1 day per developer, ~2 days of upfront enablement, and 2–3 sprints before the pattern is used consistently rather than ceremonially.
Bottom line for the TPM: 2.3.0 is a maintenance-positive, non-breaking release that confirms the package is a portable convention dependency rather than Laravel infrastructure. It does not change the recommendation — bounded pilot, behind an internal interface, with a named owner and a standing willingness to vendor it — but it adds one concrete gate before we commit: verify the Symfony 8 support did not raise our PHP floor or pull in hard dependencies.
How can I help you explore Laravel packages today?