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

Pet*_*Fox 28 php laravel laravel-5

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

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

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

Lau*_*nce 63

  • 命令是即将发生的事情.即"CreateUser"
  • 事件是刚刚发生的事情- 即"UserSuccessfullyCreated"

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

  • 必须专门调用/分派命令.即如果你想做CommandX - 你必须在某处调用CommandX.
  • 事件响应应用程序中任何位置触发的事件.最棒的是多个事件处理类可以响应同一个事件.

让我们举一个例子来说明它.假设我们创建了一个用户,我们希望向他们发送欢迎电子邮件,并更新我们的新闻通讯列表.

在Command Scenario中可以做到

AdminController {

    function create() {
            Bus::dispatch(new CreateUser(Auth::user());
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在我们的CommandClass中 - 我们会这样做

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

但是如果我们使用事件 - 我们会在CommandClass中执行类似的操作

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

然后我们可以创建尽可能多的事件,因为我们想要听取该事件并做一些事情:

EventClassA

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

EventClassB

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

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

另外 - 如果我们想在用户注册后添加另一个函数 - 比如在乐透画中输入它们 - 你可以添加另一个事件类并添加一个新的事件监听器.

EventClassC

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

请注意我们根本不需要触摸命令CreateUser类代码?这提供了OOP风格方法中类的真正分离关注点.


Mah*_*alt 5

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

主要区别在于命令可以更改模型状态,而事件只是对状态更改做出反应.

命令:

Laravel中的命令代表Command设计模式的实现.

命令的主要冒险:

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

在Laravel 5中创建一个命令:

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

例: php artisan make:command Course/PostCourseCommand

命令的命名约定:说出业务语言并向其添加postfix命令

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

$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
);
Run Code Online (Sandbox Code Playgroud)

最后:

您可以将处理程序函数及其逻辑从命令DTO分离到Handlers目录,以执行此操作:

  1. 通过工匠生成命令处理程序

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

  1. 从Command类中删除SelfHandling接口,以便它搜索处理它的处理程序.

事件:

Laravel中的事件代表了Observer设计模式的实现.

在Laravel 5中创建一个事件:

  1. 使用工匠: 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
   ],
],    
Run Code Online (Sandbox Code Playgroud)

召唤(开火)一个事件:

使用:

Event::fire(New LogSomething());

或者你可以使用事件助手

event(New LogSomething());

附注:或者您可以通过在服务提供程序中注册事件然后运行此命令来生成事件.

php artisan event:generate <<这将自动为您添加两个类

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

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

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