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

时间:2014-08-28 08:36:07

标签: php symfony laravel domain-driven-design

对于ddd和命令模式,我认为这更像是一个普遍的问题(因此不受php限制)。

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

public function createAction($title, $content)
{
    $this->commandBus->execute(new CreatePostCommand($title, $content);

    $this->render('…'); // what if the command execution failed?
}

对此有何想法?

2 个答案:

答案 0 :(得分:1)

我认为如果您真的想要遵循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。

答案 1 :(得分:0)

我目前正在这样做的方式如下(借此很长的帖子)。

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);
}

这样,您的服务就是管理命令处理程序可能返回的各种结果,而您的控制器只是为了管理您希望返回到表示层的响应。

相关问题