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]);
这些事件只会发生在本地对象上,而不是全局发生。