maximebf/events

此包已被废弃,不再维护。未建议替代包。

PHP5.3 的事件库

1.0.0 2012-12-27 11:24 UTC

This package is not auto-updated.

Last update: 2024-05-25 10:55:23 UTC


README

PHP 5.3+ 的事件库

Build Status

事件提供了一种事件调度器,可以通过多种方式监听事件。

$dispatcher = new Events\EventDispatcher();

$dispatcher->on('car.forward', function($e) {
    echo "The car is goind forward";
});

$dispatcher->notify(new Events\Event(null, 'car.forward'));

查看 example.php 以获得完整示例。

安装

安装 Events 最简单的方式是使用 Composer,以下为所需要求

{
    "require": {
        "maximebf/events": ">=1.0.0"
    }
}

或者,您可以 下载存档,并将 src/ 文件夹添加到 PHP 的 include 路径

set_include_path('/path/to/src' . PATH_SEPARATOR . get_include_path());

Events 不提供自动加载器,但遵循 PSR-0 规范
您可以使用以下代码片段来自动加载 Events 类

spl_autoload_register(function($className) {
    if (substr($className, 0, 6) === 'Events') {
        $filename = str_replace('\\', DIRECTORY_SEPARATOR, trim($className, '\\')) . '.php';
        require_once $filename;
    }
});

监听事件

事件通过 Events\EventDispatcher 类进行通知。注册监听器以处理事件的简单方法是使用 on() 方法

  • on($event_name, $callback):监听指定名称的事件,可以使用通配符(*)字符
  • on($regexp, $callback):监听名称与正则表达式匹配的事件
  • on($callback):监听所有事件
  • on($object):使用对象的 "on" 方法进行监听(见下文)

$callback 可以是任何 PHP 可调用函数(即回调 - 字符串或数组 - 或闭包)。它将只接收一个 Events\Event 对象作为其唯一参数。

$dispatcher->on('car.forward', function($e) {});
$dispatcher->on('car.*', function($e) {});
$dispatcher->on('/^car\.(.+)$/', function($e) {});
$dispatcher->on(function($e) {});

当使用 on($object) 时,该对象应具有以驼峰式命名的、以 "on" 开头的方法。例如:方法 onCarForward() 将监听名为 car.forward(或 car_forward 或 car-forward)的事件。

class CarListener {
    public function onCarForward($e) {}
}

$dispatcher->on(new CarListener());

多个监听器可以监听同一事件。但是,其中一些可能比其他更重要。这可以通过将整数作为 on() 方法的第三个参数来指定。数值越高,重要性越大。

$dispatcher->on('car.forward', function($e) {}, 100);

事件由发送者、名称和一些参数组成。事件对象有以下方法

  • getSender():返回发出事件的对象
  • getName():返回事件的名称
  • getParam($name, $default=null):返回 $name 参数
  • getParams()

对于某些事件,可能需要返回值。监听器可以使用 setReturnValue($value) 指定返回值。

某些事件可能允许取消它们所代表的操作。这可以通过使用 cancel() 来执行。

最后,如果多个监听器处理一个事件,其中一个可以使用 stopPropagation() 停止事件传播到其他监听器。

$dispatcher->on('method_call', function($e) {
    if ($e->getParam('method_name') === 'foobar') {
        $e->cancel();
    } else {
        $e->setReturnValue(true);
    }
});

在底层,当调用 on() 方法时,事件调度器会创建一个类型为 Events\EventListener 的监听器对象。您可以创建自定义监听器对象,并使用 addListener() 添加它们。

调度事件

可以使用事件调度器的 notify($event) 方法调度事件。事件必须是类型为 Events\Event 的对象。

$dispatcher->notify(new Events\Event($sender, $name, $params));

notify() 返回一个布尔值,指示事件是否被一个或多个监听器处理。

如果您想确保事件至少被一个监听器接收,可以使用 notifyUntil($event, $callback=null)。此方法将尝试传递事件,如果失败,将尝试与未来添加的任何监听器。当事件被处理时,将调用 $callback

$dispatcher->notifyUntil(new Events\Event(null, 'foo'), function() {
    echo "Event processed!";
});

为了简化事件通知的过程,可以使用Events\Notifier对象来创建和分发事件。它的构造函数需要传入事件分发器和发送者对象作为必选参数。您可以可选地提供事件名称的前缀,并指定使用不同的事件类。提供的方法有notify()notifyUntil(),但它们的形式略有不同。它们不是接收事件对象,而是接收事件名称以及可选的参数数组。

$notifier = new Events\Notifier($eventDispatcher, $sender);
$notifier->notify('foobar', array('param1' => 'value'));

其他实用工具

您可以使用Events\GenericEmitter创建可以发射事件的对象,并在此对象上注册监听器。

class Car extends Events\GenericEmitter {
    protected $eventPrefix = 'car.';
    public function forward() {
        $this->notify('forward');
    }
}

$car = new Car();
$car->on('car.forward', function($e) {});

事件发射器可以充当中继器。因此,如果您有一个全局事件分发器,可以通过将特定发射器作为监听器添加到全局事件分发器中,来中继该发射器的事件。

$car = new Car();
$dispatcher = new Events\EventDispatcher();

$car->on('car.forward', function($e) {});
$dispatcher->on('car.forward', function($e) {});

$car->addListener($dispatcher);

可以使用Events\EventProxy类作为任何对象的代理,并且每当访问属性或调用方法时,都会发射事件。

$object = new Events\EventProxy(new MyClass(), $dispatcher);
$dispatcher->on('proxy.call', function($e) {
    if ($e->getParam('method') === 'foobar') {
        echo "Foobar was called!";
    }
});
$object->foobar();

您可以通过实现Events\EventListener接口来创建自定义事件监听器。

class CustomListener implements Events\EventListener {
    public function match(Event $e) {
        // checks if the event can be handled by this listener
        return $e->getName() === 'foobar';
    }
    public function handle(Event $e) {
        // do something with $e when match() returned true
        echo $e->getName();
    }
}

$dispatcher->addListener(new CustomListener());