在 Drupal 8 中创建 hook_init

在 Drupal 7 中开发站点时,我发现hook_init()钩子是快速测试代码中某些内容的好方法。通过添加少量代码块,可以构建复杂的 SQL 查询、检查内部配置,甚至测试复杂的节点交互。

当我开始在 Drupal 8 中开发站点时,我发现我需要一个类似的机制来做类似的事情。然而,这个hook_init()钩子在 Drupal 8 中不再存在,所以我需要寻找另一种方法来做到这一点。

为了在 Drupal 8 中做到这一点,我们需要利用事件订阅者。有几种不同类型的事件订阅者可用,但为了使用它们,我们需要创建一个小模块。

这是info.yml一个名为 hook_init 的模块的文件。

name: Hook Init
type: module
description: 'Testing stuff.'
core: 8.x

在这个模块中,我们创建了一个 hook_init.services.yml 文件,我们用它来向事件订阅者注册一个名为 HookInitEventSubsciber 的类。我们在这里不详细说明什么样的事件,我们只是注册将处理该细节的类。

services:
  hook_init.event_subscriber:
    class: Drupal\hook_init\EventSubscriber\HookInitEventSubscriber
    tags:
      - { name: event_subscriber }

HookInitEventSubsciber 类实现了 EventSubscriberInterface 接口,因此必须实现一个名为 的静态函数getSubscribedEvents()。这个静态函数返回一个我们想要触发的事件数组,以及我们应该触发这个类中的哪些函数。

在该类中,我使用了 KernelEvents::CONTROLLER 事件,该事件在找到用于处理请求的控制器时触发。触发事件方法 (onLoad) 传递一个 FilterControllerEvent 对象,该对象可用于更改被调用的控制器或传递给它的参数。这在加载过程中已经很晚了,因此 Drupal 被引导,并且有很多关于请求的可用信息。在这个类中,我们只是使用这个方法来拦截页面请求,所以我们在这里没有对 FilterControllerEvent 对象做任何事情。

<?php
 
namespace Drupal\hook_init\EventSubscriber;
 
use \Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
 
class HookInitEventSubscriber implements EventSubscriberInterface {
 
  public static function getSubscribedEvents() {
 
    $events[KernelEvents::CONTROLLER][] = array('onLoad');
 
    return $events;
  }
 
  public function onLoad(FilterControllerEvent $event) {
    drupal_set_message('Event triggered.');
  }
 
}

激活此模块后,每次加载页面时,屏幕上都会显示“事件触发”消息。我应该注意到,这在很大程度上是一个测试和开发模块,不应在生产中使用。也就是说,我已经使用这种系统来创建允许我记录 Drupal 触发的不同事件或与之交互的事件。事件订阅者系统非常强大,这个简单的例子展示了如何轻松挂钩 Drupal 中的核心事件以检查或更改请求的结果。

还有一些其他的 KernelEvents 事件可供使用,详见该类的文档。