定制 solidframe/cqrs 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

solidframe/cqrs

最新稳定版本:v0.1.0

Composer 安装命令:

composer require solidframe/cqrs

包简介

CQRS building blocks: Command, Query, Handlers, and Bus implementations for SolidFrame

README 文档

README

Command Query Responsibility Segregation: CommandBus, QueryBus, Handlers, and Middleware.

Commands produce side effects and return nothing. Queries return data and produce no side effects.

Installation

composer require solidframe/cqrs

Quick Start

Define a Command and Handler

use SolidFrame\Cqrs\Command;
use SolidFrame\Cqrs\CommandHandler;

final readonly class PlaceOrder implements Command
{
    public function __construct(
        public string $orderId,
        public string $customerId,
    ) {}
}

final readonly class PlaceOrderHandler implements CommandHandler
{
    public function __construct(private OrderRepository $orders) {}

    public function __invoke(PlaceOrder $command): void
    {
        $order = Order::place(
            new OrderId($command->orderId),
            new CustomerId($command->customerId),
        );

        $this->orders->save($order);
    }
}

Define a Query and Handler

use SolidFrame\Cqrs\Query;
use SolidFrame\Cqrs\QueryHandler;

final readonly class GetOrderById implements Query
{
    public function __construct(public string $orderId) {}
}

final readonly class GetOrderByIdHandler implements QueryHandler
{
    public function __construct(private OrderRepository $orders) {}

    public function __invoke(GetOrderById $query): ?OrderDto
    {
        $order = $this->orders->find(new OrderId($query->orderId));

        return $order ? OrderDto::fromEntity($order) : null;
    }
}

Dispatch

// Command — fire and forget
$commandBus->dispatch(new PlaceOrder(
    orderId: 'order-123',
    customerId: 'customer-456',
));

// Query — get result
$order = $queryBus->ask(new GetOrderById(orderId: 'order-123'));

Standalone Usage

Without a framework bridge, wire the bus manually:

use SolidFrame\Cqrs\Handler\InMemoryHandlerResolver;
use SolidFrame\Cqrs\Bus\CommandBus;
use SolidFrame\Cqrs\Bus\QueryBus;

$resolver = new InMemoryHandlerResolver();
$resolver->register(PlaceOrder::class, new PlaceOrderHandler($orders));

$commandBus = new CommandBus($resolver);
$commandBus->dispatch(new PlaceOrder('order-123', 'customer-456'));

Middleware

Add cross-cutting concerns to bus processing.

use SolidFrame\Core\Middleware\MiddlewareInterface;

final readonly class TransactionMiddleware implements MiddlewareInterface
{
    public function __construct(private Connection $connection) {}

    public function handle(object $message, callable $next): mixed
    {
        $this->connection->beginTransaction();

        try {
            $result = $next($message);
            $this->connection->commit();

            return $result;
        } catch (\Throwable $e) {
            $this->connection->rollBack();
            throw $e;
        }
    }
}

// With middleware
$commandBus = new CommandBus($resolver, [
    new TransactionMiddleware($connection),
    new LoggingMiddleware($logger),
]);

Middleware executes in registration order. Each middleware calls $next($message) to pass to the next one.

Handler Resolution

Handlers are resolved by the message type passed to __invoke(). The convention:

  • PlaceOrder command → PlaceOrderHandler::__invoke(PlaceOrder $command)
  • GetOrderById query → GetOrderByIdHandler::__invoke(GetOrderById $query)

One handler per command/query. Multiple handlers for the same message type will throw an exception.

API Reference

Class / Interface Purpose
Command Marker interface for commands
Query Marker interface for queries
CommandHandler Marker interface for command handlers
QueryHandler Marker interface for query handlers
CommandBus Dispatches commands through middleware to handlers
QueryBus Dispatches queries through middleware to handlers
MessageBus Abstract base for both buses
HandlerResolverInterface Contract for resolving handlers
InMemoryHandlerResolver In-memory handler registry
HandlerNotFoundException Thrown when no handler matches

Related Packages

Contributing

This repository is a read-only split of the solidframe/solidframe monorepo, auto-synced on every push to main. Issues, pull requests, and discussions belong in the monorepo.

统计信息

  • 总下载量: 6
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 9
  • 依赖项目数: 0
  • 推荐数: 2

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-04-18