了解成功的 Drupal 站点更新的更新和更新后挂钩
已发表: 2023-04-25在核心更新或模块更新期间,确保您的 Drupal 网站的稳定性和完整性至关重要。 幸运的是,Update API 模块和 Update/Post Update Hooks 可以提供帮助。
Update API 模块提供更新 Drupal 站点上的代码和模块所必需的挂钩。 这些挂钩只不过是更新和更新后挂钩,它们允许开发人员根据他们的需要自定义更新。
在本文中,我们将讨论更新 API、什么是更新和更新后挂钩以及何时以及如何使用它们。 通过了解这两种类型的挂钩,您可以毫不费力地成功更新您的 Drupal 站点。 让我们开始吧!

更新 API
在现有站点上工作时,当您更新模块中的代码时,您可能需要更新存储的数据,以便存储的数据与新代码兼容。 您可能已经注意到诸如“网站遇到意外错误”之类的错误在您面前闪过。 可怕吧!? 我知道! 这就是 Drupal 的更新 API 来拯救我们的地方。
如果更新是在同一主要版本的 Drupal 核心中的模块的两个次要版本之间进行的,则可以使用更新 API 来更新数据。 更新 API 允许您提供代码,以便在您的模块对其数据模型进行更改时对存储的数据执行更新。 数据模型更改是指任何使现有站点上存储的数据与该站点更新后的代码库不兼容的更改。 这些数据模型更改涉及:
更新配置架构
- 添加/删除/重命名配置键。
- 更改配置键的数据类型。
- 更改配置键的预期默认值等。
更新数据库架构
- 添加/更改/删除数据库表或字段。
- 将存储的数据移动到不同的字段或表。
- 更改存储数据的格式等
更新实体和字段
- 向现有实体类型添加新的基本字段。
- 将字段从过时类型更新为新类型等。
更新数据
- 操作现有站点上的存储数据。
使用更新挂钩
Hook hook_update_N() 用于在模块的次要版本之间引入更新。 这些挂钩位于您的模块中的*.install文件中。
hook_update_N() 的写法是(模块名)_update_(编号)。 这里N包括:
- 1 位或 2 位数字表示 Drupal 核心兼容性(Drupal 8、9、10 等)
- 接下来的 1 位是您模块的主要发布版本
- 顺序计数的最后2位,从01开始
例子:
example_update_9201(): 9.x-2.x 版本的第一次更新。
其中“example”是模块的名称,第一个数字表示 Drupal 核心版本“9”,数字“2”表示模块的主要发布版本,最后两位数字“01”表示为编写的第一个更新函数模块“示例”。
挂钩实现函数的数字部分(即上例中的 9201)存储在数据库中,以跟踪哪些更新已被执行。 所以你不应该重新编号更新函数。
要了解模块“存储在数据库中的示例”的当前模式版本,请使用:
drush php-eval "echo drupal_get_installed_schema_version('example');"

要手动将模块“example”的当前架构版本设置回“9201”,请使用:
drush php-eval "echo drupal_set_installed_schema_version('example', '9201');"

注意:请尽量避免在生产站点上使用 drupal_set_installed_schema_version() 函数,因为它会直接更新您的数据库。 您可以在开发期间在本地或较低的测试环境中使用它来重置模式版本。
在 update hook 函数之前的文档块注释中添加适当的描述,因为它将在运行时为用户打印。
Structure of hook_update_N(): /** * A aimple hook_update_N() hook. */ function example_update_9201() { // Code goes here. }
这些钩子按排序顺序执行,即 example_update_9201() 钩子在 example_update_9202() 之前执行,接下来是 9203、9204 等等。
您还可以通过引入挂钩之间的依赖关系来更改这些挂钩的排序顺序。 使用挂钩 hook_update_dependencies() 在两个更新挂钩之间运行更新。

所有更新挂钩都是批量执行的,它们还支持项目的批量处理。 所有更新挂钩都可以访问 $sandbox 参数,该参数可用于在更新挂钩中创建批处理,以便一次处理大量数据而不会导致任何 PHP 超时。
添加新配置密钥的更新挂钩的简单示例:
目前,example_module.settings.yml 文件包含:



要向配置添加新的密钥“描述”:
- 将“描述”键添加到设置文件

- 在 example_module.install 文件中添加 update_hook:

- 使用 drush updb 运行挂钩。

- 检查更新后的配置,新密钥“描述”已更新。

使用 Post Update 挂钩
Hook hook_post_update_NAME(),类似于update hook,用于引入更新。 但是这个钩子主要用于更新数据,比如实体。 这些挂钩在所有 hook_update_N() 挂钩运行后执行。 在此阶段,Drupal 已经完全修复,因此您可以在站点内使用任何 API。
这些挂钩位于模块中的 *.post_update.php 文件中。
hook_post_update_NAME() 的写法是(模块名称)_post_update_(任意名称)。 这里的NAME可以是任意的机器名。 文件中函数的这种字母数字命名是确保此挂钩执行顺序的唯一因素。
与更新挂钩类似,在 post_update 挂钩之前的文档块注释中添加适当的描述。 另外,不要重复使用相同的钩子名称。
hook_post_update_NAME() 的结构:
/** * A aimple hook_post_update_NAME() hook. */ function example_post_update_test() { // Code goes here. }
就像更新挂钩一样,使用 $sandbox 参数来指示 Batch API 应该用于您的 post_update 挂钩。
使用更新后挂钩更新术语数据的简单示例:
- 目前,标签词汇表下的所有术语都有一个禁用的“测试示例”字段。

- 在 example_module.post_update.php 文件中添加一个 post_update 挂钩,为所有现有术语启用“测试示例”字段。

- 使用 drush updb 运行挂钩。

- 验证更新的术语数据,必须启用复选框“测试示例”。

如何运行这些钩子!
您可以使用 Drush 命令执行这些挂钩,drush updb。它按以下步骤构建批处理:
- 发现所有更新挂钩。
- 解决依赖关系并对它们的顺序进行排序。
- 放置钩子用于批处理。
- 接下来,发现所有 Post 挂钩。
- 如果有 post_update 挂钩,并且 update_hook 之前运行过,则缓存被清除。
- 然后,将每个 post_update 挂钩推送到批处理中。
- 执行批处理。
post-update hook 相对于 update hook 的一个主要优势是 Drupal 在运行 post-update 时功能齐全。 这允许开发人员在使用更新后挂钩的同时使用任何 Drupal 服务。 使用更新挂钩,不能假设 Drupal 已完全修复并避免调用其他挂钩、实体 API 等。
最后的想法
当尝试通过更新配置/数据库架构来修复您的站点时,请尝试使用更新挂钩。 当涉及到操作存储的数据、重新保存配置、更新内容实体、清除缓存等时,更新后挂钩更适合使用。
老实说,Drupal.org 上没有关于何时使用哪个钩子的明确文档! 有一个未解决的问题要求改进关于这两个钩子的使用的文档,如果你愿意,你可以贡献它。
但是根据开发者的经验,以Drupal 9 & 10核心模块为例,使用update hooks对配置或数据库执行CRUD操作(即修复站点),使用post-update hooks对CRUD内容实体(然后修复更新站点上的数据),因为更新后挂钩在更新挂钩之后运行。
喜欢阅读这篇文章吗? 向我们表达爱意并订阅我们的每周时事通讯!