laravel-bus maintained by net-code
net-code/laravel-bus
Attribute-routed command and query buses for Laravel, with a configurable middleware pipeline.
- A command/query is a plain object carrying a
#[HandledBy(Handler::class)]attribute. - The bus resolves the named handler from the container and invokes it (
__invoke). - Handlers run inside a middleware pipeline you configure per bus.
Extracted from the net-tech portfolio API so the CQRS kernel can be shared across projects.
Install
composer require net-code/laravel-bus
The service provider is auto-discovered. It binds CommandBus, QueryBus and
TransactionManager and wires the default middleware.
Usage
use NetCode\Bus\Command\Command;
use NetCode\Bus\Command\CommandHandler;
use NetCode\Bus\Command\HandledBy;
#[HandledBy(CreateUserHandler::class)]
final readonly class CreateUser implements Command
{
public function __construct(public string $email) {}
}
final readonly class CreateUserHandler implements CommandHandler
{
public function __invoke(CreateUser $command): string
{
// ...
return $id;
}
}
use NetCode\Bus\Command\CommandBus;
$id = app(CommandBus::class)->dispatch(new CreateUser('a@b.c'));
Queries are identical via NetCode\Bus\Query\* and QueryBus::ask().
Middleware
Ships with:
TransactionMiddleware(command bus) — wraps each handler in a DB transaction.LoggingQueryMiddleware(query bus) — logs each dispatched query at debug level.
Both defaults are configurable. Publish the config to change them:
php artisan vendor:publish --tag=bus-config
// config/bus.php
return [
'command' => ['middleware' => [
NetCode\Bus\Laravel\TransactionMiddleware::class,
App\Bus\AuthorizeMiddleware::class, // your own
]],
'query' => ['middleware' => [
NetCode\Bus\Laravel\LoggingQueryMiddleware::class,
]],
];
Middleware are resolved from the container (constructor injection works) and applied
outermost-first. Custom middleware implement CommandMiddleware / QueryMiddleware.
Transactions
TransactionMiddleware depends on NetCode\Bus\TransactionManager, bound by default to
LaravelTransactionManager (uses the default DB connection). Rebind it to change the
transaction boundary.
License
MIT