Laravel 5 上下文中的命令和事件有什么区别?

What's the difference between Commands and Events in the context of Laravel 5?

所以 Laravel 5 终于在昨天发布了命令总线的最终实现,但我一直在徘徊,我们在以前的版本中使用命令总线而不是事件机制的真正区别是什么?

好的,我明白了它可以用于从 Request 对象创建命令的原因,这非常有用,但除此之外,它似乎以类似的方式表现,甚至是现在的事件的整个排队功能?

能否提供用例示例以及两者的优缺点?

  • 命令是即将立即发生的事情。即 "CreateUser"
  • 事件是刚刚现在发生的事情 - 即"UserSuccessfullyCreated"

差异似乎很小 - 但有一些关键差异。

  • 命令必须明确 called/dispatched。 IE。如果你想 执行 CommandX - 您必须在某处调用 CommandX。
  • 事件 响应 在您的应用程序中触发 任何地方 的事件。 最棒的是多事件处理 classes 可以响应 同样的 事件.

让我们举个例子来最好地说明一下。假设我们创建了一个用户,我们想向他们发送一封欢迎电子邮件并更新我们的时事通讯列表。

在命令场景中会做

AdminController {

    function create() {
            Bus::dispatch(new CreateUser(Auth::user());
    }
}

然后在我们的命令中Class - 我们会做

public function handle(CreateUser $auth)
{
     // 1. Create the user here
     // 2. Send welcome email
     // 3. Update our newsletter
}

但是如果我们使用事件——我们会在我们的命令中做这样的事情Class

public function handle(CreateUser $auth)
    {
         // 1. Create the user here
         Event::fire(new UserWasCreated($user));
    }

然后我们可以创建任意数量的事件来监听该事件并做一些事情:

事件ClassA

Event::listen('UserWasCreated', function($event)
{
    // 2. Send welcome email
});

事件ClassB

Event::listen('UserWasCreated', function($event)
{
    // 3. Update our newsletter
});

最棒的是关注点分离。命令 "createuser" 现在不需要担心 用户创建后会发生什么。它只需要 CreateUser.

另外 - 如果我们想在用户注册后添加另一个功能 - 比如在乐透抽奖中输入它们 - 你可以添加另一个事件 Class 并添加一个新的事件监听器。

事件ClassC

Event::listen('UserWasCreated', function($event)
{
    // 4. Register them in lotto
});

注意到我们完全不需要触摸命令 CreateUser class 代码 了吗?这在 OOP 样式方法中提供了 classes 的真正分离问题。

我只想在正确答案之上分享我对这个概念的理解:

主要区别在于命令可以更改模型状态,而事件仅对状态更改作出反应。

命令:

Laravel 中的命令表示 Command 设计模式的实现。

命令的主要成就:

  • 可以从任何地方访问
  • 任何其他开发人员都非常容易阅读它们

要在 Laravel 5 中创建命令:

您需要生成命令DTO(可以实现SelfHandling接口)。使用 php artisan make:command {command-name}

示例:php artisan make:command Course/PostCourseCommand

命令的命名约定:讲业务语言,加上后缀命令

要从您的控制器调用(调度)命令,您可以使用:

$this->dispatch(new PostCourseCommand())

Bus::dispatch(new PostCourseCommand());

旁注: “从请求中分派”功能是一种很好的方法,可以跳过将变量一个一个地传递给命令构造函数,相反它会为您解决这个问题:

示例:

$test_request = Request::create('/test', 'GET', [
   'name' => 'Mahmoud',
   'nickname' => 'Mega'
]);

$result = Bus::dispatchFrom(
   CreateCourse::class, $test_request
);

最后:

您可以将处理函数及其逻辑从命令 DTO 分离到 Handlers 目录,这样做:

  1. 通过artisan
  2. 生成命令处理程序

art handler:command --command="Course/PoatCourseCommand"

  1. 从 Command class 中删除 SelfHandling 接口,这样它将搜索处理程序来处理它。

事件:

Laravel 中的事件表示 Observer 设计模式的实现。

要在 Laravel 5 中创建事件:

  1. 使用artisan:art make:event {event-name}

示例:art make:event LogSomething

  1. 为该事件生成事件处理程序

art handler:event LogSomething --event="LogSomething"

  1. 在事件服务提供者中注册事件及其处理程序(app/Providers/EventServiceProvider.php)

示例:

protected $listen = [    
   \Zzz\Events\LogSomething::class => [ // event.name
      \Zzz\Handlers\Events\LogSomething::class, //EventListener
   ],
],    

调用(触发)事件:

使用:

Event::fire(New LogSomething());

或者你可以使用事件助手

event(New LogSomething());

旁注: 或者,您可以通过简单地在服务提供商中注册事件然后 运行 此命令来生成事件。

php artisan event:generate << 这会自动为您添加两个 classes

您也可以在不创建事件处理程序或在侦听器数组中注册侦听器的情况下侦听事件,只需转到事件服务证明程序并在引导函数中编写您的事件及其操作(不推荐)。示例:

Event::listen('XXX\Events\DoSomethingElse', function($event)
{
    dd('handle me :)');
});

最后:您可以在 class 本身内对事件进行排队,甚至订阅多个事件..