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

Command Bus Bundle Laravel Package

itmedia/command-bus-bundle

A Symfony bundle that adds command bus support, letting you dispatch commands to dedicated handlers and keep business logic decoupled from controllers. It integrates with the service container for handler registration and execution.

View on GitHub
Deep Wiki
Context7

Getting Started

Before anything else, note the mismatch in the brief: this is a Symfony bundle, not a Laravel package. If you are evaluating it from a Laravel codebase, the answer is "skip it" — Laravel's Illuminate\Bus / dispatch() already covers this ground, and pulling in a Symfony bundle is not viable. The notes below assume a Symfony (or Symfony-compatible) host application.

v0.5.0 is a small compatibility release: its release note only advertises PHP 7.4 and 8 support. There is no documented new feature, middleware, async transport, or API change in the release note, so treat it as a compatibility bump rather than a reason to re-architect anything.

Minimal steps:

  1. composer require itmedia/command-bus-bundle and pin the exact tag you test against (v0.5.0 as of this review).
  2. Register the bundle in config/bundles.php (new Itmedia\CommandBusBundle\CommandBusBundle()).
  3. Read in this order: the README (short, Russian description only — "Реализация CommandBus"), then src/ for the bus service class and the handler interface, then the bundle's DependencyInjection/ folder to see how handlers are collected (almost certainly via a service tag, e.g. command_bus.handler or similar).
  4. Inspect what the bundle actually registers: bin/console debug:container command_bus and bin/console debug:container --tag=<handler_tag>. This is faster than reading docs that may not exist.

First use case: a single synchronous command with a handler, wired and dispatched from a controller. Do not start with middleware, async transport, or return-value semantics — get one command round-tripping first, because most of the uncertainty in a package this small is in how handlers are discovered, not in the dispatch call itself. The v0.5.0 release note does not change that ordering.

A realistic shape:

final class RegisterUser { public function __construct(public string $email) {} }

final class RegisterUserHandler {
    public function __invoke(RegisterUser $command): void { /* ... */ }
}

Then tag/register the handler per the bundle's convention and $commandBus->dispatch(new RegisterUser($email)) from the controller.

Implementation Patterns

Command as a dumb DTO. Keep commands immutable, scalar-only, serializable. The moment you stuff an entity or a service into a command you lose the ability to test it in isolation and to ever move it onto an async transport.

Handler-per-command, injected by the container. Handlers should be thin: validate preconditions, load aggregates via repositories, persist, return. Business logic belongs in domain services the handler calls, not in the handler body — otherwise the "one handler per command" symmetry breaks down and handlers become god classes.

Controller → bus, never controller → handler. The value of the bus is that the controller knows nothing about handler location. Enforce this in review: any use App\Handler\... inside a controller is a smell.

Middleware/decorator for cross-cutting concerns. Rather than baking logging, transactions, or auth checks into every handler, wrap the bus or register middleware (whatever extension mechanism the bundle exposes — check src/ for a middleware interface or a tagged-iterator of "middlewares"). Transaction-wrapping the whole dispatch is the single highest-value middleware: one DB transaction per command, and handlers stay clean.

Testing. Because commands are DTOs and handlers are plain services, unit-test handlers by instantiating them with mocked repositories — no container, no bus. Then have a small number of integration tests that go through the real bus to catch wiring/tagging regressions. That split catches ~all the failure modes and runs fast.

If you outgrow it: the bundle is small enough that replacing it with a hand-rolled CommandBus (a ContainerInterface + a command → handler map) is a day's work. Design your application so the bus is behind your own interface, so the swap is mechanical.

Gotchas and Tips

  • Maintenance risk is still the headline. v0.5.0 is a PHP 7.4/8 compatibility release, not evidence of an active feature roadmap. The package remains small, with minimal dependents and thin documentation. Pin the exact tag/commit, and treat the bundle as "code you now own" — be prepared to fork. For a new project, a first-party Symfony messenger setup covers the same ground with real maintenance.
  • Thin documentation. The description is one line in Russian. Budget time to read src/; don't assume dispatch() returns the handler's return value — many minimal buses return void. Verify explicitly, because returning a value from a handler and silently getting null is the classic first-day bug here. The v0.5.0 note gives no API-level clarification.
  • Handler discovery is the usual failure point. If "no handler for command" appears, check the service tag is applied (autoconfigure in services.yaml may or may not cover it — a bundle-specific tag usually needs an explicit _instanceof rule or manual tagging). debug:container --tag=... is the fastest diagnostic.
  • Autowiring collisions. If two handlers claim the same command, behavior depends on registration order — silently non-deterministic. Add a compile-time check or at least a test that asserts an exception on duplicate registration.
  • No async story. This is a synchronous in-process bus. If you need queued/retried commands later, you are migrating to Messenger; plan the seam now (own interface, no direct bundle types in your domain code).
  • PHP/Symfony version drift. v0.5.0 explicitly targets PHP 7.4 and 8, so the PHP-side compatibility story is better than the older release. That does not prove compatibility with your Symfony DI version: a bundle this small may still lag current Symfony service-definition signatures. Run the container compile and the test suite on your target PHP/Symfony combination before committing — deprecation noise here is often a hard break, not a warning.
  • Extension point: if the bundle exposes middleware, that is the only sane place to add transactions, logging, and metrics. If it doesn't, decorate the bus service in your own services.yaml — that works regardless of what the bundle offers and is a better long-term bet than editing vendor code.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
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