Event 类提供了一个简单的观察者实现,允许您在应用程序中订阅和监听事件。例如,您可以监听用户登录的时间并更新他们的上次登录日期。
Event::listen('auth.login', function($user) {
$user->last_login = new DateTime;
$user->save();
});此事件通过在用户登录逻辑中调用的 Event::fire 方法提供,从而使该逻辑可扩展。
Event::fire('auth.login', [$user]);有关 October CMS 本身提供的所有事件列表,请参阅 API 文档。
Event::listen 方法主要用于订阅事件,并且可以在应用程序代码的任何位置执行。第一个参数是事件名称。
Event::listen('acme.blog.myevent', ...);第二个参数可以是一个闭包,用于指定当事件被触发时应该发生什么。该闭包可以接受由触发事件提供的一些可选参数。
Event::listen('acme.blog.myevent', function($arg1, $arg2) {
// Do something
});您还可以传递对任何可调用对象或专用事件类的引用并将使用它来代替。
Event::listen('auth.login', [$this, 'LoginHandler']);可调用方法可以选择指定所有、部分或不指定任何参数。 无论哪种方式,事件都不会抛出任何错误,除非它指定了过多的参数。
最常见的位置是一个 插件注册文件 的 boot 方法。
class Plugin extends PluginBase
{
// ...
public function boot()
{
Event::listen(...);
}
}或者,插件可以在插件目录中提供一个名为 init.php 的文件,您可以使用它来放置事件注册逻辑。例如:
Event::listen(...);由于这些方法本身都没有哪个是“正确”的,请根据你的应用程序的规模,选择一种你觉得适合的方法。
您也可以在订阅事件时,将优先级指定为第三个参数。具有更高优先级的监听器将会首先运行,而具有相同优先级的监听器将会按照订阅顺序运行。
// Run first
Event::listen('auth.login', function() { ... }, 10);
// Run second
Event::listen('auth.login', function() { ... }, 5);有时你可能希望停止事件传播到其他监听器。 你可以通过从你的监听器返回 false 来实现:
Event::listen('auth.login', function($event) {
// Handle the event
return false;
});在注册事件监听器时,您可以使用星号来指定通配符监听器。通配符监听器会接收首先触发的事件名称,接着是作为数组传递给事件的参数。
以下监听器处理所有以 foo. 开头的事件。
Event::listen('foo.*', function($event, $params) {
// Handle the event...
});您可以使用 Event::firing 方法来准确地确定哪个事件被触发了。
Event::listen('foo.*', function($event, $params) {
if (Event::firing() === 'foo.bar') {
// ...
}
});您可以在代码的任何位置使用 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');In some cases, you may wish to use a class to handle an event rather than a Closure. Class event listeners will be resolved out of the Application IoC container, providing you with the full power of dependency injection on your listeners.
事件类可以像其他任何类一样,使用 Event::listen 方法注册,传入类名作为字符串。
Event::listen('auth.login', LoginHandler::class);默认情况下,LoginHandler 类上的 handle 方法将被调用:
class LoginHandler
{
public function handle($data)
{
// ...
}
}如果您不想使用默认的 handle 方法,您可以指定应订阅的方法名称。
Event::listen('auth.login', [LoginHandler::class, 'onLogin']);事件订阅者是可以在类本身内部订阅多个事件的类. 订阅者应该定义一个 subscribe 方法, 该方法将被传递一个事件调度器实例.
class UserEventHandler
{
/**
* subscribe register the listeners for the subscriber.
* @param Illuminate\Events\Dispatcher $events
* @return array
*/
public function subscribe($events)
{
$events->listen('auth.login', [static::class, 'userLogin']);
$events->listen('auth.logout', [static::class, 'userLogout']);
}
/**
* userLogin handles user login events.
*/
public function userLogin($event)
{
// ...
}
/**
* userLogout handles user logout events.
*/
public function userLogout($event)
{
// ...
}
}一旦订阅者被定义,它就可以通过 Event::subscribe 方法进行注册。
Event::subscribe(new UserEventHandler);您也可以使用 应用 IoC 容器 来解析您的订阅者。为此,只需将订阅者的名称传递给 subscribe 方法即可。
Event::subscribe(UserEventHandler::class);有时你会希望将事件绑定到对象的单个实例。你可以通过在你的类中实现 October\Rain\Support\Traits\Emitter 特性来使用另一种事件系统。
class UserManager
{
use \October\Rain\Support\Traits\Emitter;
}此特质提供了一个方法,用于使用 bindEvent 监听事件。
$manager = new UserManager;
$manager->bindEvent('user.beforeRegister', function($user) {
// Check if the $user is a spammer
});该 fireEvent 方法用于触发事件。
$manager = new UserManager;
$manager->fireEvent('user.beforeRegister', [$user]);这些事件只会发生在本地对象上,而非全局。