logo

额外区块类型 (EBT) - 全新的布局构建器体验❗

额外区块类型 (EBT) - 样式化、可定制的区块类型:幻灯片、标签页、卡片、手风琴等更多类型。内置背景、DOM Box、JavaScript 插件的设置。立即体验布局构建的未来。

演示 EBT 模块 下载 EBT 模块

❗额外段落类型 (EPT) - 全新的 Paragraphs 体验

额外段落类型 (EPT) - 类似的基于 Paragraph 的模块集合。

演示 EPT 模块 滚动

滚动

9.2. 在 Drupal 中,“hook” 是什么意思?

17/10/2025, by Ivan

本文旨在让您熟悉 Drupal,我们将在添加自定义模块后编写代码示例。

Drupal 并不是一个完美无缺、无需改动的单体系统。客户经常会要求在网站上添加某些功能。为了在保持 Drupal 核心代码完整的同时扩展其功能,我们使用模块(module)。模块化系统使得 Drupal 的功能得以扩展。但如果我们想要扩展一个现成的第三方计数器模块怎么办?当然,我们可以在 drupal.org 上创建一个 issue,申请添加我们需要的功能,也许一个月、两个月……甚至一年或两年后,才能在该模块中获得我们所需的功能。但我们也可以换一种方式——自己编写需要的代码。为了扩展 Drupal 附加模块及其自身的功能,我们会在自己的模块中使用钩子(hook)插件(plugin)

核心思想是:我们不需要直接维护 Drupal 核心或附加模块的代码,这样能在开发成本上节省大量支出。为了能够轻松更新 Drupal 核心与模块代码,绝不能修改核心代码或第三方模块。否则,当模块或核心升级时,您的所有更改都会被覆盖。

为了实现模块与 Drupal 核心之间,以及模块与模块之间的交互,Drupal 拥有一个钩子系统(hook system)。钩子本质上是一个函数回调(callback),即当代码执行到某个钩子时,会调用我们在模块中定义的对应函数代码。通过这种方式,我们可以在任何时候处理用户数据、菜单、分类法、以及不同内容类型的节点(如修改、添加、删除或加载显示等)。Drupal 8 中的钩子数量相当多,但比 Drupal 7 少了一些,因为许多钩子被 Symfony 组件替代实现:

https://api.drupal.org/api/drupal/core%21core.api.php/group/hooks/8.2.x

如果查看 Drupal 7 的版本,你会发现需要滚动很久:

https://api.drupal.org/api/drupal/includes%21module.inc/group/hooks/7.x

但这并不意味着 Drupal 8 功能减弱了,只是原本通过 hook 实现的功能,在 Drupal 8 中需要通过添加合适的插件(plugin)来实现。

如果仔细查看 Drupal 8 中的钩子列表,会发现许多钩子名称结尾是 _alter,这表示该钩子用于修改变量的值。例如:

hook_form_alter() — 允许在 Drupal 处理表单时修改表单数组。稍后我们会分析 Drupal 如何通过数组生成表单。要在模块中应用此钩子,与其他钩子一样,我们只需编写如下函数:

function mymodule_form_alter() {
  // 修改表单数组
}


我在示例中简化了代码,未写出函数参数或命名空间。现在我们只需理解钩子的工作原理。mymodule 是我们模块的名称,我们将单词 “hook” 替换为模块名,Drupal 会自动识别并执行该函数,从而修改表单数组。

它是如何实现的?在 prepareForm 方法中,会调用另一个 alter() 方法:

$this->moduleHandler->alter($hooks, $form, $form_state, $form_id);

这意味着,每个实现了 hook_form_alter() 的模块都会在此处插入自己的代码。由此可见,如果我们想在 Drupal 中某处插入自定义代码,首先应考虑使用钩子;其次考虑使用插件;只有在确实无法通过插件实现时,才会去修改(打补丁 / hack)模块代码(虽然这通常是不得已的做法)。目前,我们还未遇到需要修改插件的任务,所以接下来让我们学习如何编写自己的模块。