php应用程序中的命令模式:如何处理控制器操作


Command pattern in php applications: how to handle controller actions?

我认为这更多是一个关于ddd和命令模式的一般性问题(因此不受php限制)。

假设我在控制器的创建操作中执行CreatePostCommand,该命令将被处理并最终成功执行。如果命令失败或成功,通知控制器返回哪个响应的适当方式是什么?如果命令处理程序将触发特定于域的事件,我可以将控制器连接到该事件,但这似乎很尴尬,也不适合所有情况(例如,可以在其他地方创建帖子,而控制器真的不知道这一点:))。

public function createAction($title, $content)
{
    $this->commandBus->execute(new CreatePostCommand($title, $content);
    $this->render('…'); // what if the command execution failed?
}

对此有什么想法吗?

我认为,如果您真的试图遵循DDD命令模式,那么您需要将命令总线视为一个火,忘记可能需要很长时间才能完成的异步过程。

请考虑立即重定向到命令验证器控制器。这取决于命令验证器主动检查命令的状态,看看它是否有效。

在大多数情况下,命令将成功完成,然后您的验证器可以再次重定向以继续正常流。

如果命令失败,则验证器会显示一条适当的错误消息。

如果该命令正在执行中,则可以在通知用户该命令正在进行的同时完成整个重定向循环。

类似于:

// Execute the command
$command = new CreatePostCommand($title, $content);
$this->commandBus->execute($command);
return redirect '/command-verifier/' . $command->getId();
// The verification action
public function verifyCommandAction($commandId)
$commandStatus = $this->commandBus->getStatus($commandId);
if ($commandStatus == SUCCESS) redirect to all is well;
if ($commandStatus == FAILED) then oops;
if ($commandStatus == IN_PROGRESS) then maybe pause a bit and redirect again while keeping the user informed.

很明显,有很多人在挥手,但我认为这是最通用的方法,尤其是php,其中每个请求都从零开始。

我目前做这件事的方式如下(请原谅长帖子)。

public function createAction($title, $content) {
    try {
        $post = $this->commandBus->execute(new CreatePostCommand($title, $content);
    }
    catch (Exception $e) {
        return $this->render('some error template file', $e);
    }
    return $this->render('successful creation template file', $post);
}

通过这种方式,您正在创建一个帖子,如果一切按计划进行,则返回$post对象并将其发送到您的视图中。另一方面,当在执行过程中抛出异常时,您会捕获该错误并将其发送到视图。

我的首选方法是让控制器调用管理该行为的服务上的方法,并将控制器注入作为管理响应的侦听器,即:

public function createAction($title, $content) {
    $service = new CreateActionService($title, $content);
    return $service->create($this);
}
public function onError(Exception $e) {
    return $this->render('some error template file', $e);
}
public function onSuccess($post) {
    return $this->render('success', $post);
}

然后为你服务。。。

public function create($listener)
{
    try {
        $this->commandBus->execute(new CreatePostCommand($title, $content);
    }
    catch (Exception $e) {
        return $this->listener->onError($e);
    }
    return $this->listener->onSuccess($post);
}

通过这种方式,您的服务可以管理命令处理程序可能返回的各种结果,而您的控制器只需管理您可能希望返回到表示层的响应。