Installation
composer require averor/message-bus
Publish the config (if needed):
php artisan vendor:publish --provider="Averor\MessageBus\MessageBusServiceProvider"
Define a Command
Create a command class (e.g., app/Commands/ProcessOrder.php):
namespace App\Commands;
use Averor\MessageBus\Command;
class ProcessOrder implements Command
{
public function __construct(
public string $orderId,
public float $amount
) {}
}
Define a Handler
Create a handler (e.g., app/Handlers/ProcessOrderHandler.php):
namespace App\Handlers;
use App\Commands\ProcessOrder;
use Averor\MessageBus\CommandHandler;
class ProcessOrderHandler implements CommandHandler
{
public function handle(ProcessOrder $command)
{
// Business logic here
return "Order {$command->orderId} processed for {$command->amount}";
}
}
Dispatch the Command In a controller or service:
use Averor\MessageBus\MessageBus;
class OrderController extends Controller
{
public function __construct(private MessageBus $bus) {}
public function store()
{
$result = $this->bus->dispatch(new ProcessOrder('123', 100.00));
return response()->json(['success' => $result]);
}
}
Register Handlers
Bind handlers in a service provider (e.g., AppServiceProvider):
public function boot()
{
$this->app->bind(
\App\Handlers\ProcessOrderHandler::class,
fn() => new \App\Handlers\ProcessOrderHandler()
);
}
Naming Conventions
*Command (e.g., CreateUserCommand).*Handler (e.g., CreateUserHandler).*Event (if using event sourcing).app/Commands/ and handlers in app/Handlers/.Automatic Handler Resolution
The package auto-resolves handlers based on command class names (e.g., ProcessOrder → ProcessOrderHandler). Override via explicit binding if needed.
Middleware for Commands Apply middleware to commands (e.g., auth, validation):
$this->bus->dispatch(new ProcessOrder('123', 100.00))
->withMiddleware(Authenticate::class)
->withMiddleware(ValidateOrder::class);
Queueable Commands Dispatch commands to queues:
$this->bus->dispatch(new ProcessOrder('123', 100.00))->delay(5)->onQueue('orders');
Event Sourcing (Optional)
Extend Averor\MessageBus\Event and use MessageBus::publish() for events:
$this->bus->publish(new OrderCreatedEvent('123'));
Mock Handlers Use Laravel’s mocking to test command dispatch:
$handler = Mockery::mock(\App\Handlers\ProcessOrderHandler::class);
$this->app->instance(\App\Handlers\ProcessOrderHandler::class, $handler);
$result = $this->bus->dispatch(new ProcessOrder('123', 100.00));
$handler->shouldHaveReceived('handle');
Command Testing Test commands in isolation:
$command = new ProcessOrder('123', 100.00);
$handler = new ProcessOrderHandler();
$result = $handler->handle($command);
$this->assertEquals("Order 123 processed for 100.00", $result);
Handler Not Found
*Handler). Explicitly bind if custom:
$this->app->bind(
\App\Handlers\CustomProcessOrderHandler::class,
fn() => new \App\Handlers\CustomProcessOrderHandler()
);
Middleware Order
$this->bus->dispatch($command)
->withMiddleware(FirstMiddleware::class)
->withMiddleware(SecondMiddleware::class); // Runs first
Circular Dependencies
Queue Failures
ShouldQueue interface for commands and handle failures in FailedJob observer:
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class ProcessOrder implements Command, ShouldQueue
{
use Queueable;
// ...
}
Log Dispatches
Enable logging in config/message-bus.php:
'logging' => true,
Check Laravel logs for dispatched commands/handlers.
Handler Execution Flow
Use tap() to inspect command/handler state:
$this->bus->dispatch($command)->tap(function ($result) {
\Log::info('Command result:', ['result' => $result]);
});
Custom Dispatcher
Extend Averor\MessageBus\Dispatcher to add logic (e.g., retry logic, metrics):
class CustomDispatcher extends Dispatcher
{
protected function beforeHandle($command, $handler)
{
// Add pre-handling logic
}
}
Bind it in AppServiceProvider:
$this->app->bind(
\Averor\MessageBus\Dispatcher::class,
fn() => new \App\CustomDispatcher()
);
Dynamic Handler Resolution
Override resolveHandler() in a custom dispatcher for dynamic resolution:
protected function resolveHandler($command)
{
return new \App\Handlers\DynamicHandler($command);
}
Event Listeners Attach listeners to commands/events:
$this->bus->dispatch($command)
->withListener(\App\Listeners\LogCommand::class);
MessageBus::batch() for bulk operations:
$this->bus->batch([
new ProcessOrder('1', 100),
new ProcessOrder('2', 200),
])->dispatch();
How can I help you explore Laravel packages today?