ecfectus/events

PHP7 事件调度器

dev-master 2016-10-03 14:31 UTC

This package is not auto-updated.

Last update: 2024-09-18 18:18:27 UTC


README

Build Status

PHP7 事件调度器,利用新的类型提示和 Ds\PriorityQueue 数据类型,以提高性能和降低复杂性。

使用方法

使用方法简单,使用 listen 添加回调,使用 fire 运行事件回调。

class TestEvent extends Ecfectus\Events\Event{
    public $value = [];
}

$dispatcher = new Ecfectus\Events\Dispatcher();

$dispatcher->listen(TestEvent::class, function(Event $e){
    $e->value[] = 2;
}, 500);

$dispatcher->listen(TestEvent::class, function(Event $e){
    $e->value[] = 1;
}, 1);

$result = $dispatcher->fire(new TestEvent()); $result->value will equal [2, 1]

通配符监听器

您还可以添加通配符事件,并且事件的优先级将得到保持。

$dispatcher->listen('TestEv*', function(Event $e){
    $e->value[] = 3;
}, 100);

$dispatcher->listen('*', function(Event $e){
    $e->value[] = 4;
}, -10);

$result = $dispatcher->fire(new TestEvent()); $result->value will equal [2, 3, 1, 4]

回调

默认情况下,回调可以是任何 callable,有关可用性的详细信息,请参阅此处 php 文档: https://php.ac.cn/manual/en/language.types.callable.php

此外,您可以设置一个解析器,当回调不可调用时,该解析器将被调用,这对于使用容器创建对象很有用。

例如,以 Laravel 风格提供事件监听器可以像这样实现

$dispatcher->setResolver(function($callback = null){

    //return a function that can be invoked
    return function(Event $e) use ($callback){

        //parse the callback into something that can be used
        list($class, $method) = explode('@', $callback);
        $instance = $somecontainer->make($class);

        //return the result of the method
        return $instance->$method($event);
    };

});

$dispatcher->listen('*', 'MyClassName@handleEvent', -10);//MyClassName is created via the resolver and the result of the handleEvent method is returned.

忘记事件

您可以通过调用 forgot 调度器方法来移除事件的所有监听器。

$dispatcher->forget(TestEvent::class); all listeners for TestEvent will be forgotten
$dispatcher->forget('*'); all listeners for the wildcard * will be forgotten

事件

事件应扩展 Ecfectus\Events\Event 类,除此之外,事件可以按您希望的方式实现。

核心事件类仅提供对调度器进行类型提示的基础,您可以在事件中包含或添加您想要的任何功能。

在将来,我们可能会添加传播功能或其他尚未确定的功能,而不是让您更改代码,我们可以将这些功能添加到核心事件类中。

为什么不允许字符串事件名称?

我们考虑了这个问题一段时间,并得出结论,使用事件名称作为类的字符串表示形式是最佳解决方案,原因有很多。

  1. 检查事件名称的类型和值的样板代码被简化为简单的 class_name 调用。
  2. 我们知道传入和传递给调度器的确切内容,因此我们可以相应地进行类型提示。
  3. IDE 和自动完成使开发者更容易,而不是记住字符串值。
  4. 在某些情况下,添加“灵活性”只会使文档更加混乱,特别是当在一个项目中,一个开发者更喜欢一种风格而不是另一种风格时,用户会感到困惑。

这样非常简单,您只需传入您的事件实例即可。

订阅者

您还可以创建订阅者类并将它们添加到调度器中,这些类必须提供 subscribe 方法,并将调度器实例传递给它们。

在订阅者的 subscribe 方法内部,您可以使用调度器作为正常操作,这对于分组事件监听器非常完美。

class NameOfSubscriberClass{

    public function subscribe($dispatcher)
    {
        $dispatcher->listen('*', function(Event $e){
            $e->value[] = 1;
        });

        $dispatcher->listen('*', function(Event $e){
            $e->value[] = 2;
        });

        //more events
    }
}

$dispatcher->subscribe('NameOfSubscriberClass');// NameOfSubscriberClass will be created for you via (new NameOfSubscriberClass())

//or pass an instance (ideal if your subscriber needs constructor arguments)
$subscriber = new NameOfSubscriberClass();
$dispatcher->subscribe($subscriber);