php中事件的含义

Moe*_*ini 2 php events event-handling

我也知道php和nodejs,在javascript中我们有异步编程,所以我理解了事件的含义.但我在Yii和Zend 2中看到了Event并使用它们,但我无法理解它的含义,它是怎么回事在PHP中工作,它究竟在做什么?

Yan*_*ang 12

首先,PHP中没有事件

事件是带有名称的回调函数的抽象.通常,我们将它们定义为$eventName => $listener,其中$listener是一个回调函数$eventName

事件和常规回调函数有什么区别?

再次 - 要记住的核心要点是事件是回调函数.而已.

它们之间的唯一区别是我们如何调用它们.

在引导步骤中使用其必需参数定义事件,但在没有参数的情况下按需调用.虽然回调函数仅使用参数调用

考虑这个例子,

<?php

$eventManager = new EventManager();
$eventManager->attach('my_event', function(){

   print_r(func_get_args());

}, array('foo', 'bar'));
Run Code Online (Sandbox Code Playgroud)

正如我们刚刚定义的一个事件,我们会调用,

$eventManager->trigger('my_event');

这将输出: Array([0] => [foo], [1] => [bar]

这与JavaScript有关!

由于我们大多数人都熟悉JavaScript甚至驱动的架构,因此值得一提的是它的常见用法示例:

var a = document.getElementsByTagName('a')[0];
a.onclick = function(event) { // <-- We define an event with the event argument
   event.preventDefault();
   alert('A element was clicked');
}

a.click(); // <-- but we invoke it without arguments

// or If you want a Jquery
$("a").click(function(event){
   event.preventDefault();
   alert('A element was clicked');
});

$("a").click();
Run Code Online (Sandbox Code Playgroud)

因为在PHP中我们没有这种事件驱动的性质,我们可以用我们自己的类替换它来管理事件并充分利用它.

为何使用它们?

虽然事件让很多人感到困惑,但它们非常有用.

想象一下,您有一个内容管理系统(CMS),您的用户可以决定如何处理404错误.说,他们可以处理

1)显示空白页
2)重定向到/
3)显示自定义消息

没有事件你就必须这样做,比如

if ($router->isMatched($request)){

    //do dispatch etc

} else {

   // Here you start handling 404 errors

   switch($config->read('404_way_handle')){

       case 'show_blank':
          die();
       break;

       case 'show_msg':
          echo 'Some custom message';
       break;

       case 'redirect':
          // do redirect
       break;
   }
}
Run Code Online (Sandbox Code Playgroud)

通过事件,您可以简化可读性并使代码更易于维护:

if ($router->isMatched($request)){
   // do dispatch
} else {

   $eventManager->trigger('404_handler');
}
Run Code Online (Sandbox Code Playgroud)

虽然404_handler本身看起来像

  $eventManager->attach('404_handler', function(){

       switch($config->read('404_way_handle')){

           case 'show_blank':
              die();
           break;

           case 'show_msg':
              echo 'Some custom message';
           break;

           case 'redirect':
              // do redirect
           break;
       }

  }, $config);
Run Code Online (Sandbox Code Playgroud)


所以让我们分解吧

1)事件提高了可读性,这对未来很有帮助

2)事件确实遵循单一责任原则,因为您可以简单地$eventManager向需要它的类注入,而回调函数可能会破坏它或者也可能引入全局状态(这对单元测试是不利的).

3)有不同类型的逻辑 - 模板逻辑,业务逻辑,错误处理程序逻辑,数据访问逻辑等.事件通过将业务(或其他类型)逻辑与其配置逻辑分离来简化您的应用程序逻辑,以便您最终具有明确的应用逻辑.

如果你想知道他们如何在Zend Framework 2中工作,你可以观看这个讲座(即使你不熟悉Zend Framework 2也要观看它)

MVC相关架构中的事件

既然你一直在谈论框架,那么值得一提的是,MVC-related架构中也可能存在事件.由于事件是回调函数,因此您可以boostrap在类似MVC的体系结构中抽象常见事件.

$mvcEvent->on(MVC_EVENT::ROUTE_MATCH, function(){

  $mvcEvent->on(MVC_EVENT::DISTPATCH, function($content){

    echo $mvcEvent->trigger(MVC_EVENT::RENDER, $content);

  });

});
Run Code Online (Sandbox Code Playgroud)

注意:在纯MVC理论中,根本没有事件.它们确实充当帮助者,但是再次 - 在框架中,您可以抽象它们并将它们称为"事件".