Events

基本用法

Event 类提供了一个简单的观察者实现,允许您订阅和监听应用程序中的事件。例如,您可以监听用户何时登录并更新他们的上次登录日期。

Event::listen('auth.login', function ($user) {
    $user->last_login = new DateTime;
    $user->save();
});

这是可用的事件Event::fire 作为用户登录逻辑的一部分调用的方法,从而使逻辑可扩展。

Event::fire('auth.login', [$user]);

订阅事件

Event::listen 方法主要用于订阅事件,可以在应用程序代码中的任何位置完成。第一个参数是事件名称。

Event::listen('acme.blog.myevent', ...);

第二个参数可以是一个闭包,它指定触发事件时应该发生什么。闭包可以接受可选的一些参数,由触发事件.

Event::listen('acme.blog.myevent', function ($arg1, $arg2) {
    // Do something
});

您还可以传递对任何可调用对象或专用事件类 而这将被使用。

Event::listen('auth.login', [$this, 'LoginHandler']);

NOTE:可调用方法可以选择指定全部、部分或不指定任何参数。无论哪种方式,事件都不会抛出任何错误,除非它指定了太多错误。

在哪里注册听众

最常见的地方是boot 一个方法插件注册文件.

class Plugin extends PluginBase
{
    [...]

    public function boot()
    {
        Event::listen(...);
    }
}

或者,插件可以提供一个名为init.php 在可用于放置事件注册逻辑的插件目录中。例如:

<?php

Event::listen(...);

由于这些方法都不是天生“正确”的,因此请根据您的应用程序的大小选择一种您觉得合适的方法。

使用优先订阅

您还可以在订阅事件时指定优先级作为第三个参数。具有较高优先级的监听器将首先运行,而具有相同优先级的监听器将按照订阅的顺序运行。

// Run first
Event::listen('auth.login', function () { ... }, 10);

// Run second
Event::listen('auth.login', function () { ... }, 5);

NOTE:通配符侦听器不支持优先级。

停止事件

有时您可能希望停止将事件传播到其他侦听器。您可以返回false 来自您的听众:

Event::listen('auth.login', function ($event) {
    // Handle the event

    return false;
});

通配符监听器

注册事件侦听器时,您可以使用星号来指定通配符侦听器。通配符侦听器将收到首先触发的事件名称,然后是作为数组传递给事件的参数。

下面的监听器将处理所有以foo..

Event::listen('foo.*', function ($event, $params) {
    // Handle the event...
});

$event 提供被触发的事件名称。 $params 是事件负载。这将是从触发事件传递的参数数组。

给定以下事件:

Event::fire('foo.event', function ($arg1, $arg2) {
   // ...
}

使用通配符侦听器时,这将映射到以下内容:

Event::listen('foo.*', function ($event, $params) {
    $arg1 = $params[0];
    $arg2 = $params[1];
}

触发事件

您可以使用Event::fire 在代码中的任何位置添加方法以使逻辑可扩展。这意味着其他开发人员,甚至您自己的内部代码,都可以“挂钩”到代码的这一点并注入特定的逻辑。第一个参数应该是事件名称。

Event::fire('myevent')

用你的插件命名空间代码作为事件名称的前缀总是一个好主意,这将防止与其他插件发生冲突。

Event::fire('acme.blog.myevent');

第二个参数是一个值数组,将作为参数传递给事件监听器 订阅它。

Event::fire('acme.blog.myevent', [$arg1, $arg2]);

第三个参数指定事件是否应该是一个暂停事件,这意味着如果返回“非空”值,它应该停止。默认情况下,此参数设置为 false。

Event::fire('acme.blog.myevent', [...], true);

如果事件正在停止,则返回的第一个值将被捕获。

// Single result, event halted
$result = Event::fire('acme.blog.myevent', [...], true);

否则,它以数组的形式返回所有事件的所有响应的集合。

// Multiple results, all events fired
$results = Event::fire('acme.blog.myevent', [...]);

通过引用传递参数

在处理或过滤传递给事件的值时,您可以在变量前加上& 通过引用传递它。这允许多个侦听器操纵结果并将其传递给下一个。

Event::fire('cms.processContent', [&$content]);

监听事件时,参数也需要用& 闭包定义中的符号。在下面的示例中,$content 变量将在结果后附加“AB”。

Event::listen('cms.processContent', function (&$content) {
    $content = $content . 'A';
});

Event::listen('cms.processContent', function (&$content) {
    $content = $content . 'B';
});

排队的事件

触发事件可以推迟与队列结合.使用Event::queue 方法来“排队”触发事件但不立即触发它。

Event::queue('foo', [$user]);

您可以使用Event::flush 刷新所有排队事件的方法。

Event::flush('foo');

使用类作为监听器

在某些情况下,您可能希望使用类来处理事件而不是闭包。类事件监听器会解析出来应用程序 IoC 容器,为您提供对侦听器的依赖注入的全部功能。

订阅个别方法

事件类可以注册到Event::listen 像任何其他方法一样,将类名作为字符串传递。

Event::listen('auth.login', 'LoginHandler');

默认情况下,handle 上的方法LoginHandler 类将被称为:

class LoginHandler
{
    public function handle($data)
    {
        // ...
    }
}

如果您不想使用默认值handle 方法,您可以指定应订阅的方法名称。

Event::listen('auth.login', 'LoginHandler@onLogin');

订阅整个课程

事件订阅者是可以从类本身内部订阅多个事件的类。订阅者应该定义一个subscribe 方法,该方法将传递一个事件调度程序实例。

class UserEventHandler
{
    /**
     * Handle user login events.
     */
    public function userLogin($event)
    {
        // ...
    }

    /**
     * Handle user logout events.
     */
    public function userLogout($event)
    {
        // ...
    }

    /**
     * Register the listeners for the subscriber.
     *
     * @param  Illuminate\Events\Dispatcher  $events
     * @return array
     */
    public function subscribe($events)
    {
        $events->listen('auth.login', 'UserEventHandler@userLogin');

        $events->listen('auth.logout', 'UserEventHandler@userLogout');
    }
}

一旦定义了订阅者,它就可以注册到Event::subscribe 方法。

Event::subscribe(new UserEventHandler);

您也可以使用应用程序 IoC 容器 解决您的订户。为此,只需将您的订阅者的姓名传递给subscribe 方法。

Event::subscribe('UserEventHandler');

事件发射器特征

有时您希望将事件绑定到对象的单个实例。您可以通过实现Winter\Storm\Support\Traits\Emitter 你班级里的特质。

class UserManager
{
    use \Winter\Storm\Support\Traits\Emitter;
}

这个特性提供了一种监听事件的方法bindEvent.

$manager = new UserManager;
$manager->bindEvent('user.beforeRegister', function ($user) {
    // Check if the $user is a spammer
});

NOTE:目前不支持此特征的通配符侦听器。

fireEvent 方法用于触发事件。

$manager = new UserManager;
$manager->fireEvent('user.beforeRegister', [$user]);

这些事件只会发生在本地对象上,而不是全局发生。

豫ICP备18041297号-2