A message bus library

Maintainers

Package info

github.com/MikeGeorgeff/bus

pkg:composer/georgeff/bus

Statistics

Installs: 19

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-02-12 02:55 UTC

This package is auto-updated.

Last update: 2026-05-19 21:07:42 UTC


README

A command bus library for PHP 8.2+.

Installation

composer require georgeff/bus

Usage

Defining Commands and Handlers

A command is any plain object. A handler is a callable — typically a class with an __invoke method.

class SendEmail
{
    public function __construct(
        public readonly string $to,
        public readonly string $subject,
        public readonly string $body,
    ) {}
}

class SendEmailHandler
{
    public function __invoke(SendEmail $command): void
    {
        // send the email
    }
}

Dispatching Commands

The Dispatcher resolves a handler for the given command and executes it.

use Georgeff\Bus\Dispatcher;

$dispatcher = new Dispatcher($resolver);

$dispatcher->dispatch(new SendEmail(
    to: 'user@example.com',
    subject: 'Welcome',
    body: 'Hello!',
));

Handler Resolvers

A resolver takes a command class name and returns a callable handler. Two implementations are provided.

SimpleResolver

Instantiates the handler directly. Suited for handlers with no constructor dependencies.

use Georgeff\Bus\Resolver\SimpleResolver;

$resolver = new SimpleResolver($locator);

PsrContainerResolver

Retrieves the handler from a PSR-11 container. Use this when handlers have dependencies.

composer require psr/container
use Georgeff\Bus\Resolver\PsrContainerResolver;

$resolver = new PsrContainerResolver($container, $locator);

Handler Locators

A locator maps a command class name to a handler class name. Two implementations are provided.

InMemoryLocator

Uses an explicit command-to-handler map.

use Georgeff\Bus\Locator\InMemoryLocator;

$locator = new InMemoryLocator([
    SendEmail::class => SendEmailHandler::class,
]);

ClassNameLocator

Resolves handlers by convention — appends Handler to the command class name. SendEmail resolves to SendEmailHandler in the same namespace.

use Georgeff\Bus\Locator\ClassNameLocator;

$locator = new ClassNameLocator();

Middleware

The MiddlewareAwareDispatcher wraps any dispatcher with a middleware pipeline. Each middleware receives the command and a $next callable.

use Georgeff\Bus\MiddlewareAwareDispatcher;

$logging = function (object $command, callable $next): mixed {
    echo 'Dispatching ' . $command::class . PHP_EOL;

    $result = $next($command);

    echo 'Dispatched ' . $command::class . PHP_EOL;

    return $result;
};

$dispatcher = new MiddlewareAwareDispatcher(
    new Dispatcher($resolver),
    [$logging],
);

$dispatcher->dispatch(new SendEmail(/* ... */));

Middleware executes in the order provided. Each middleware can:

  • Run logic before and after the handler
  • Short-circuit by not calling $next
  • Modify the return value

Full Example

use Georgeff\Bus\Dispatcher;
use Georgeff\Bus\MiddlewareAwareDispatcher;
use Georgeff\Bus\Resolver\PsrContainerResolver;
use Georgeff\Bus\Locator\InMemoryLocator;

$locator = new InMemoryLocator([
    SendEmail::class => SendEmailHandler::class,
]);

$resolver = new PsrContainerResolver($container, $locator);

$dispatcher = new MiddlewareAwareDispatcher(
    new Dispatcher($resolver),
    [$logging, $transaction],
);

$dispatcher->dispatch(new SendEmail(
    to: 'user@example.com',
    subject: 'Welcome',
    body: 'Hello!',
));

License

MIT