astrotechlabs/yii2-tactician

Yii 2 命令总线模式实现

1.2.5 2022-01-26 20:27 UTC

This package is auto-updated.

Last update: 2024-09-24 17:22:06 UTC


README

Packagist PHP Version Support GitHub stars GitHub forks GitHub repo size GitHub license

这是一个用于 Tactician 命令总线库 的 Yii 框架 2 包装器/适配器。它提供了一种简单的方法在基于 Yii2 的应用程序中使用命令总线模式。

何时应该使用命令总线?

如果你有一个服务层,Tactician 就是一个很好的选择。如果你不确定服务层是什么,Martin Fowler 的 PoEAA 是一个很好的起点。Tactician 的作者也对此主题进行了演讲。

命令可以帮助捕捉用户意图。它们在涉及表单或期望 getter/setter 对象的序列化库时,也可以很好地替代模型。

命令总线本身很容易装饰额外的行为,如锁定或数据库事务,因此可以通过插件轻松扩展。

作者:tactician.thephpleague.com

何时不应该使用它?

如果你的应用程序非常小,不需要服务层,那么 Tactician 对你来说可能没有太大帮助。

如果你已经在使用提供命令总线的工具(如 Broadway),你那里可能也还好。

作者:tactician.thephpleague.com

安装

$ composer require astrotechlabs/yii2-tactician

设置

首先,你必须配置你的 Yii 依赖注入容器,以便能够在其中使用命令和处理类。

在你的 config/web.php 中应该有类似以下的内容

$config = [
    'id' => 'your-app-id',
    //...
    'container' => [
        'definitions' => [
            MyClassCommand::class => MyClassHandler::class 
        ]
    ],
    'components' => [
        //...
    ]
];

重要:你必须遵循以下约定

  • 你的 命令 类必须以 Command 结尾;
  • 你的 处理类 必须是: 相同命令类名 + 去掉命令后缀 + Handler

最后一个是注册 Yii2TacticianCommandBus 组件到你的 config/web.php 文件,如下所示

$config = [
    'id' => 'your-app-id',
    //...
    'container' => [
        'definitions' => [
            MyClassCommand::class => MyClassHandler::class 
        ]
    ],
    'components' => [
        'commandBus' => [
            'class' => AstrotechLabs\Yii2Tactician\Yii2TacticianCommandBus::class
        ],
        // other components...
    ]
];

如何使用

映射命令和处理类

在应用程序的某个地方定义一个 Command 类,例如

class MyClassCommand
{
    public $someParam;
    public $someOtherParam;

    public function __construct($someParam, $someOtherParam = 'defaultValue')
    {
    	$this->someParam = $someParam;
        $this->someOtherParam = $someOtherParam;
    }
}

定义你的 Handler 类应该是这样的

class MyClassHandler
{
    public function handle(MyClassCommand $command)
    {
    	// do command stuff here!
        // we can use $command->someParam and $this->someOtherParam
    }
}

现在我们可以在控制器或任何你想使用它的地方使用这个命令

public function actionDoSomething()
{
    $queryParam = Yii::$app->getRequest()->get('some_param');
    
    // Here the magic happens! =)
    $result = Yii::$app->commandBus->handle(new MyClassCommand($queryParam));

    if ($result === true) {
    	return $this->redirect(['go/to/some/place']);
    }

    return $this->render('some-awesome-view');
}

使用字符串路径

你可以将命令类用作 字符串路径 而不是具体对象。为此,只需这样做

$config = [
    'id' => 'your-app-id',
    //...
    'container' => [
        'definitions' => [
            // you can use any string here.
            'awesome.alias.to.be.called.anywhere' => MyClassHandler::class 
        ]
    ],
    'components' => [
        //...
    ]
];

你的 处理类 应该如下所示

class MyClassHandler implements AstrotechLabs\Yii2Tactician\Handler
{
    public function handle(MyClassCommand $command)
    {
    	// do command stuff here!
        // we can use $command->someParam and $this->someOtherParam
    }
    
    public function commandClassName(): string
    {
        return MyClassCommand::class;
    }
}

重要:以这种方式,你的 处理类 必须实现 AstrotechLabs\Yii2Tactician\Handler 接口,并且你的 命令类 必须实现 AstrotechLabs\Yii2Tactician\Command

你的控制器动作或任何其他地方

public function actionDoSomething()
{
    $result = Yii::$app->commandBus->handle('awesome.alias.to.be.called.anywhere', [
        'someParam' => 'abc',
        'someOtherParam' => 'def'
    ]);
    
    // .. other logics
}

在底层,命令总线系统将调用

MyClassHandler::handle($command);

其中 $command 参数在该处创建,如下所示

MyClassCommand::create([someParam' => 'abc', 'someOtherParam' => 'def']);

享受 =)

作者

还可以参考参与此项目的 贡献者 列表。

贡献

欢迎提交拉取请求。对于重大更改,请先创建一个问题来讨论您希望进行的更改。

请确保适当更新测试。

许可证

本软件包遵循MIT许可证发布。有关详细信息,请参阅附带的LICENSE文件。

参考文献