Laravel 5 Command Bus的最佳实践

时间:2015-07-09 01:49:04

标签: php laravel laravel-5

我正在尝试重构控制器,并看看Laravel的命令总线。

在阅读了大量文章并观看了一些视频后,似乎这可能是重构控制器的好方法。

然而,似乎我不应该从命令中返回任何东西。

  

使用命令时   你遵循命令查询分离(CQS)原则:一个功能是   查询(即它返回某些内容)或命令(即它)   影响国家)。两者都是相互排斥的。所以命令不是   应该返回任何内容,并且不应该修改查询   任何东西。   source

我创建了命令CreateCustomerCommand

namespace App\Commands;

use QuickBooks_IPP_Service_Customer;

use App\Commands\Command;
use Illuminate\Contracts\Bus\SelfHandling;

class CreateCustomer extends Command implements SelfHandling
{
    private $qb;
    private $customer_service;
    private $customer;
    private $is_same_address;
    private $name;
    private $primary_phone;
    ...

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->qb = Quickbooks::Instance();
        $this->qb->ipp->version(QuickBooks_IPP_IDS::VERSION_3);

        $this->customer_service = new QuickBooks_IPP_Service_Customer();

        $this->is_same_address = $request->input('customer.isSameAddress');
        $this->name = ucwords(strtolower($request->input('customer.name')));
        $this->primary_phone = $request->input('customer.primaryPhone');
    }
    ...

    /**
     * Execute the command.
     *
     * @return void
     */
    public function handle()
    {
        $this->customer->setDisplayName($this->name);

        ...

        $this->customer_service->add(...);



    }
}

关于最佳实践的三个问题:

  1. 致电$this->customer_service->add()后,将返回客户id。如何将此id发送回控制器?

  2. 合并活动日志最好放在哪里?

  3. 的活动:

    $activity = new Activity();
    $activity->event = 'Created Customer: ' . $this->name;
    $activity->user = Auth::user()->name;
    $activity->save();
    

    最好在CreateCustomerCommand结束时加入此内容吗?

    1. 活动怎么样?
    2. 事件:

      event(new CustomerWasCreatedOrUpdated);
      

      我是应用程序架构的新手,正在寻找一种方法来保持控制器的简单性和可维护性。如果有人能指出我正确的方向,我会很高兴。

1 个答案:

答案 0 :(得分:5)

首先,对您努力保持控制器“简单易维护”的称赞。你可能并不总能实现这一目标,但实现这一目标往往会得到回报。

如何将ID发送回控制器?

命令是一般服务的专门案例。您的命令可以自由地声明询问更改状态结果的其他公共方法。如果CLI应用程序使用该命令,则该应用程序可能会执行echo $this->command->getAddedCustomerId()之类的操作。基于Web的控制器可以类似地使用它。

但是,您引用的建议 - 无论是在没有输出的情况下更改状态还是在输出中进行查询 - 都是圣人。如果您正在更改状态,则需要知道更改该状态的结果,您可能正在滥用命令。

作为类比,请考虑Linux命令“useradd”,您可以像useradd -m 'Clara Barton' cbarton一样调用它。该命令运行并为您提供成功或失败指示。但请注意,您为其提供了主键,“cbarton”。您可以单独查询该密钥,例如grep cbarton /etc/passwd,但重要的是useradd没有为您创建ID。

总之,更改状态的命令最多应该告诉您成功或失败。如果您希望检查该状态更改的结果,您应该为该命令提供查找状态更改所需的密钥。

所以你可能想要的是一般服务。命令可能使用该服务,控制器可能使用该服务,模型可能使用该服务。但是服务只是执行一项工作的通用类,并为您提供必要的API。

合并活动日志的位置?

假设您没有使用PHP-AOP,应该在整个开发生命周期中预先建立并遵循严格而严格的活动记录实践。

在很大程度上,活动日志的位置取决于系统的主要架构模型。如果你严重依赖事件,那么一个好的地方可能是Event外观或日志事件的扩展。如果您广泛依赖DI,那么您可以在您决定需要记录的代码中传递Logger。

在命令的特定情况下,您可以选择任何一种方式,这取决于您的主要建筑模型。如果您避开了事件,那么您将通过Laravel的正常类型提示DI注入记录器。如果您利用了事件,那么您可能会执行Event::fire('log', new LogState('Blah Blah', compact ($foo, $bar)));

之类的操作

尽管如此,最重要的是您依赖可插拔和可配置的日志服务,您可以将其换出并调整测试,质量保证和生产需求。

活动怎么样?

嗯,事件很棒。直到他们不是。根据我的经验,事件可能真的变得复杂,因为他们,IMO,滥用传递数据并影响状态。

事件就像传送器一样:你走的是一条路,然后事件就会发生,然后突然你被传送到整个代码库并在一个完全不同的地方弹出,然后你做了一些事情然后被丢弃了回到原来的位置。当事件发挥作用时,你必须以某种方式思考并有效地遵循代码。

如果Laravel事件是你第一次介绍事件,我会劝阻你不要大量使用它们。相反,我建议你将它们限制在一个特定的包或应用程序的一部分,直到你感受到它们提供的功能,以及它们所需的架构和开发严谨性。