think-codee / laravel-command-bus
描述
Requires
- php: ^8.2
- laravel/framework: ^11.0
Requires (Dev)
- mockery/mockery: ^1.6
- orchestra/testbench: ^9.0
- phpunit/phpunit: ^11.0.1
This package is not auto-updated.
Last update: 2024-10-01 14:08:49 UTC
README
此包为在Laravel应用程序中实现命令模式提供了一种简单高效的方法,允许更好地分离关注点并使代码更易于维护。
安装
使用composer安装
composer require think-codee/laravel-command-bus
可选地,您可以使用以下命令发布配置文件:
php artisan vendor:publish --tag="command-bus-config"
以下为配置文件内容:
return [ 'buses' => [ 'default' => [ 'class' => \ThinkCodee\Laravel\CommandBus\Default\Bus::class, 'interface' => \ThinkCodee\Laravel\CommandBus\Contracts\Bus::class, 'alias' => 'bus.default', 'middleware' => [], 'handler_resolver' => \ThinkCodee\Laravel\CommandBus\Resolvers\SuffixHandlerResolver::class, 'handler_method' => 'handle', ], ] ];
用法
此包允许您创建和管理多个命令总线,为Laravel应用程序中处理不同类型的命令提供了一个强大灵活的系统。特别适用于实现CQRS(命令和查询责任分离)等架构模式,该模式将读取和更新操作分离。每个总线都可以配置自己的中间件和处理器解析器,增强应用程序的模块化和组织。
定义总线
要创建一个总线,首先定义一个接口
use ThinkCodee\Laravel\CommandBus\Contracts\CommandBus; interface QueryBusInterface extends CommandBus { }
然后,创建一个实现此接口的类
use ThinkCodee\Laravel\CommandBus\Bus; class QueryBus extends Bus implements QueryBusInterface { }
您可以使用以下Artisan命令创建一个总线
php artisan command-bus:make:bus QueryBus
每个总线都必须在配置文件中进行注册。包将绑定接口到相应的类并分配一个别名
'query' => [ 'class' => \App\Buses\Query\QueryBus::class, 'interface' => \App\Buses\Query\QueryBusInterface::class, 'alias' => 'bus.query', ];
然后,您可以在应用程序中使用以下方式使用总线
use App\Buses\Query\QueryBusinterface; class Controller { public function __construct( private QueryBusInterface $queryBus, ) {} public function show(int $id) { $users = $this->queryBus->handle( new GetUserQuery($id) ); // Alternatively: // app('bus.query')->handle( // new GetUsersQuery() // ); } }
定义命令和处理程序
要定义一个命令
use ThinkCodee\Laravel\CommandBus\Contracts\Command; class GetUserQuery implements Command { public function __construct(public int $id) {} }
要定义命令的处理程序
class GetUserQueryHandler { public function handle(GetUserQuery $query) { // Handle the command, e.g., process $query->id // return User::findOrFail($query->id); } }
您可以使用以下Artisan命令创建具有处理程序的命令
php artisan command-bus:make:command GetUserQuery
定义中间件
在此包中,中间件的工作方式与标准的Laravel中间件类似。它们允许在处理命令前后运行代码,为您的命令处理逻辑添加常见行为。
要定义一个中间件,创建一个在处理之前和/或之后处理命令的类
class LogExceptionsMiddleware { public function handle(Command $command, Closure $next) { try { return $next($command); } catch (\Exception $e) { Log::error($e->getMessage()); throw $e; } } }
注册中间件
您可以使用属性将中间件注册到特定的命令处理程序
- 使用
#[Middleware]
属性向处理程序添加中间件。 - 属性的第二个参数是布尔值,true表示提前添加中间件,false(或省略)表示附加。
- 使用
#[ResetMiddleware]
属性移除为该命令(在配置中注册)的所有现有中间件,并仅应用指定的中间件。
// This will prepend LogExceptionsMiddleware to the existing middleware #[Middleware([LogExceptionsMiddleware::class], true)] class StoreUserCommandHandler { public function handle(StoreUserCommand $command): int { // Handle the command, e.g., process $command->email // $user = User::create(['email' => $command->email]); // return $user->id; } }
// Handle the command with LogExceptionsMiddleware only #[ResetMiddleware] #[Middleware([LogExceptionsMiddleware::class])] class StoreUserCommandHandler { public function handle(StoreUserCommand $command): int { // Handle the command, e.g., process $command->email // $user = User::create(['email' => $command->email]); // return $user->id; } }
您仍然可以在配置文件中注册中间件,将它们分配给特定的总线。中间件将应用于总线处理的所有命令。
'default' => [ 'class' => \ThinkCodee\Laravel\CommandBus\Default\Bus::class, 'interface' => \ThinkCodee\Laravel\CommandBus\Contracts\Bus::class, 'alias' => 'bus.default', 'middleware' => [ LogExceptionsMiddleware::class, //e.g. ExecuteWithinDatabaseTransaction ], ],
处理器解析器
每个总线都有一个处理器解析器,它确定如何为给定的命令解析合适的处理器。解析器和处理命令的方法在配置文件中为每个总线指定
'handler_resolver' => \ThinkCodee\Laravel\CommandBus\Resolvers\SuffixHandlerResolver::class, 'handler_method' => 'handle',
每个处理器解析器都必须实现HandlerResolver
接口。《SuffixHandlerResolver》默认随包提供。如果您有一个名为TestCommand.php
的命令,它将尝试将处理程序名称解析为同一目录下的TestCommandHandler.php
。
当命令通过解析的处理程序运行时,它将尝试使用配置文件中指定的方法。
为特定命令指定处理器
您还可以使用#[Handler]
属性为命令设置特定的处理器。第二个参数是可选的,指定要使用的方法名称。如果没有指定,将使用配置文件中的方法名称。
#[Handler(StoreUserCustomHandler::class, 'customMethod')] class StoreUserCommand { // Command implementation }
更新日志
请参阅变更日志获取关于最近更改的更多信息。
运行测试
要运行测试,请执行以下命令:
composer test