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

Cqrs Types Laravel Package

lmc/cqrs-types

Lightweight CQRS type definitions for Laravel/PHP applications, offering command, query, and handler contracts that help separate write and read concerns. Keeps business actions explicit, consistent, and easy to organize across projects.

View on GitHub
Deep Wiki
Context7

Getting Started

lmc/cqrs-types is the contract layer of the LMC CQRS stack: interfaces for commands, queries and handlers, plus base value objects. It ships no bus, no container wiring, no middleware — those live in the companion lmc/cqrs package. Treat this as the package you put in your require (not require-dev) when your domain layer needs to speak CQRS without depending on an implementation.

  1. Install both packages — the types alone give you nothing runnable:

    composer require lmc/cqrs-types lmc/cqrs
    
  2. Read composer.json first — check the PHP constraint and the autoload namespace (typically Lmc\Cqrs\Types\). The 2024-01 release means you should verify it matches your PHP version before adopting.

  3. Where to look next — src/ is small; skim it in five minutes. Look for:

    • command/query marker interfaces (e.g. CommandInterface, QueryInterface)
    • handler interfaces (CommandHandlerInterface, QueryHandlerInterface)
    • value-object base classes (string/int wrappers, IDs)
  4. First use case — a query handler:

    final class GetUserQuery implements QueryInterface
    {
        public function __construct(public readonly UserId $id) {}
    }
    
    final class GetUserHandler implements QueryHandlerInterface
    {
        public function __construct(private UserRepository $users) {}
    
        public function __invoke(GetUserQuery $query): User
        {
            return $this->users->get($query->id);
        }
    }
    

    Register the handler in your container, resolve QueryBus from lmc/cqrs, and dispatch new GetUserQuery($id). If nothing dispatches, re-check you installed lmc/cqrs — this is the single most common first-hour mistake.

Implementation Patterns

Keep the dependency arrow pointing inward. Domain and application code should type-hint only cqrs-types interfaces. Only the composition root (Laravel service provider, Symfony services.yaml, a plain bootstrap.php) should import concrete bus classes from lmc/cqrs. This is the whole reason to split the packages: you can swap or fake the bus without touching business code.

One handler per message, plain classes. Handlers don't need to extend anything — implement the interface and let the constructor inject collaborators. Commands mutate, queries return; don't mix the two in one class.

Value objects for IDs and scalars. Extend the provided base classes for UserId, Email, Money, etc. Validate in the constructor and throw a domain exception — that keeps invalid values from ever reaching a handler. Add equals() for comparisons and __toString() for logging.

Middleware for cross-cutting concerns. Wrap the bus (or use the middleware pipeline from lmc/cqrs) for logging, transaction boundaries, validation and metrics. Order matters: validation → transaction → handler, and logging should be outermost so it captures failures.

Testing is trivial by design. Because handlers are plain classes, unit-test them directly with mocked repositories — no bus needed. For integration tests, build a tiny in-memory bus that maps message class → handler callable, or mock the bus interface in controllers.

Framework wiring. In Laravel, bind the handler interfaces in a service provider and tag handlers; in Symfony, use !tagged_iterator for the handler locator. In both cases the bus needs a handler-locator service — check the lmc/cqrs README for the exact container contract.

Async commands. If you push commands onto a queue, keep command objects serializable: no closures, resources, or un-serializable services. Value objects need JsonSerializable or a fromString() factory if you round-trip them.

Gotchas and Tips

  • This package is a ghost town — 1 star, 0 dependents, last release January 2024. There are no StackOverflow answers. Pin an exact version ("lmc/cqrs-types": "1.2.3" style) and be prepared to fork if a PHP upgrade breaks it.
  • Types ≠ runtime. Installing only cqrs-types gives you interfaces and nothing else. Every "class not found" or "no handler" error traces back to this or to a forgotten handler registration.
  • Handler registration fails at dispatch, not at boot. A missing tag in your container produces a runtime exception. Add a test that asserts every class implementing CommandInterface has a corresponding handler — this catches 90% of wiring bugs before deploy.
  • No generics in PHP. The handler interface can't express "returns User for GetUserQuery". Document the expected return type in the query's docblock and, ideally, add a static-analysis baseline (PHPStan/Psalm) to enforce it.
  • Value-object equality. == on two VOs compares properties; use the provided equals() method if it exists, or you'll get subtle bugs with whitespace, casing or lazy-loaded internals.
  • Readonly and final are load-bearing. The base classes are likely final; if you need custom behaviour, implement the interface rather than fighting the inheritance. Prefer composition.
  • Debugging via decorator. Wrap the bus with a logging decorator that records message class, payload (redact secrets), duration and exception. Since the package has no built-in profiler, this is your only visibility.
  • Serialization is on you. Value objects crossing a queue, cache or log boundary need explicit jsonSerialize()/fromString(). The package won't magically hydrate them.
  • Extension points are the interfaces plus the middleware pipeline. If you find yourself wanting to modify cqrs-types itself, you probably want a decorator around the bus instead.
  • Budget for integration work. With zero dependents you are effectively the integration test for this stack — size the adoption accordingly, and consider whether a thinner in-house command/query interface would serve you better.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console