ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 事件处理 ### 基本用法 > **注意:**有关OctoberCMS本身可用的所有事件的列表,请参阅[api文档](https://octobercms.com/docs/api/translator/beforeresolve)。 本`Event`类提供了一个简单的观察器实现,允许您订阅和聆听您的应用程序事件。例如,您可以侦听用户何时登录并更新其上次登录日期。 ~~~ Event::listen('auth.login', function($user) { $user->last_login = new DateTime; $user->save(); }); ~~~ 该事件可以通过`Event::fire`称为用户登录逻辑一部分的方法使该事件可用,从而使逻辑可扩展。 ~~~ Event::fire('auth.login', [$user]); ~~~ ### [](https://octobercms.com/docs/services/events#events-subscribing)订阅事件 该`Event::listen`方法主要用于预订事件,可以在应用程序代码中的任何位置进行。第一个参数是事件名称。 ~~~ Event::listen('acme.blog.myevent', ...); ~~~ 第二个参数可以是一个闭包,它指定触发事件时应发生的情况。闭包可以接受由[fireing事件](https://octobercms.com/docs/services/events#events-firing)提供的一些可选参数。 ~~~ Event::listen('acme.blog.myevent', function($arg1, $arg2) { // Do something }); ~~~ 您也可以传递对任何可调用对象或[专用事件类](https://octobercms.com/docs/services/events#using-classes-as-listeners)的引用,并将其代替使用。 ~~~ Event::listen('auth.login', [$this, 'LoginHandler']); ~~~ > **注意**:可调用方法可以选择指定所有,部分或不指定任何参数。无论哪种方式,事件都不会抛出任何错误,除非它指定了太多错误。 ### [](https://octobercms.com/docs/services/events#event-registration)在哪里注册听众 最常见的地方是[插件注册文件](https://octobercms.com/docs/plugin/registration#registration-methods)的`boot`方法。[](https://octobercms.com/docs/plugin/registration#registration-methods) ~~~ class Plugin extends PluginBase { [...] public function boot() { Event::listen(...); } } ~~~ 另外,插件可以在插件目录中提供一个名为**init.php**的文件,您可以使用该文件放置事件注册逻辑。例如: ~~~ <?php Event::listen(...); ~~~ 由于这些方法都不是天生的“正确”方法,因此请根据应用程序的大小来选择适合的方法。 ### [](https://octobercms.com/docs/services/events#subscribing-priority)使用优先级订阅 订阅事件时,您也可以将优先级指定为第三个参数。具有较高优先级的侦听器将首先运行,而具有相同优先级的侦听器将按订阅顺序运行。 ~~~ // Run first Event::listen('auth.login', function() { ... }, 10); // Run second Event::listen('auth.login', function() { ... }, 5); ~~~ ### [](https://octobercms.com/docs/services/events#subscribing-halting)停止事件 有时您可能希望停止将事件传播到其他侦听器。您可以通过`false`从侦听器返回来使用: ~~~ Event::listen('auth.login', function($event) { // Handle the event return false; }); ~~~ ### [](https://octobercms.com/docs/services/events#wildcard-listeners)通配符侦听器 注册事件侦听器时,可以使用星号指定通配符侦听器。通配符侦听器将首先接收触发的事件名称,然后接收作为数组传递给事件的参数。 以下侦听器将处理以开头的所有事件`foo.`。 ~~~ Event::listen('foo.*', function($event, $params) { // Handle the event... }); ~~~ 您可以使用该`Event::firing`方法来确切确定触发了哪个事件: ~~~ Event::listen('foo.*', function($event, $params) { if (Event::firing() === 'foo.bar') { // ... } }); ~~~ ### [](https://octobercms.com/docs/services/events#events-firing)射击事件 您可以`Event::fire`在代码中的任何位置使用该方法以使逻辑可扩展。这意味着其他开发人员,甚至您自己的内部代码,都可以“钩住”这一点代码,并注入特定的逻辑。的第一个参数应为事件名称。 ~~~ Event::fire('myevent') ~~~ 在插件名称空间代码前添加事件名称总是一个好主意,这样可以防止与其他插件发生冲突。 ~~~ Event::fire('acme.blog.myevent'); ~~~ 第二个参数是一个值数组,这些值将作为参数传递给预订[该事件的侦听器](https://octobercms.com/docs/services/events#events-subscribing)。 ~~~ Event::fire('acme.blog.myevent', [$arg1, $arg2]); ~~~ 第三个参数指定事件是否应为[暂停事件](https://octobercms.com/docs/services/events#subscribing-halting),这意味着如果返回“非null”值,则该事件应[停止](https://octobercms.com/docs/services/events#subscribing-halting)。默认情况下,此参数设置为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', [...]); ~~~ ### [](https://octobercms.com/docs/services/events#event-pass-by-reference)通过引用传递参数 在处理或过滤传递给事件的值时,可以给变量加上前缀`&`以通过引用传递它。这使多个侦听器可以操纵结果并将其传递给下一个。 ~~~ 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'; }); ~~~ ### [](https://octobercms.com/docs/services/events#queued-events)排队事件 触发事件可以[与队列一起](https://octobercms.com/docs/services/queues)推迟。使用此`Event::queue`方法可以“排队”要触发的事件,但不能立即将其触发。 ~~~ Event::queue('foo', [$user]); ~~~ 您可以使用该`Event::flush`方法刷新所有排队的事件。 ~~~ Event::flush('foo'); ~~~ ### [](https://octobercms.com/docs/services/events#using-classes-as-listeners)使用类作为侦听器 在某些情况下,您可能希望使用类来处理事件,而不是使用Closure。类事件侦听器将在[Application IoC容器之外](https://octobercms.com/docs/services/application)进行解析,从而为您提供对侦听器的依赖项注入的全部功能。 ### [](https://octobercms.com/docs/services/events#event-class-method)订阅个别方法 事件类可以`Event::listen`像其他方法一样注册,将类名作为字符串传递。 ~~~ Event::listen('auth.login', 'LoginHandler'); ~~~ 默认情况下,该类`handle`上的方法`LoginHandler`将被调用: ~~~ class LoginHandler { public function handle($data) { // ... } } ~~~ 如果您不希望使用默认`handle`方法,则可以指定应订阅的方法名称。 ~~~ Event::listen('auth.login', 'LoginHandler@onLogin'); ~~~ ### [](https://octobercms.com/docs/services/events#event-class-subscribe)订阅整个课程 事件订阅者是可以从类本身内部预订多个事件的类。订户应定义一个`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); ~~~ 您也可以使用[Application IoC容器](https://octobercms.com/docs/services/application)解析您的订户。为此,只需将您的订户名称传递给该`subscribe`方法。 ~~~ Event::subscribe('UserEventHandler'); ~~~ ### [](https://octobercms.com/docs/services/events#event-emitter-trait)事件发射器特征 有时您想将事件绑定到对象的单个实例。您可以通过`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]); ~~~ 这些事件将仅在本地对象上发生,而不是全局上。