返回

如何在不覆盖现有格式化器的情况下调用 hook_field_[formatter_]prepare_view()?

php

在不覆盖现有格式化器的情况下调用 hook_field_[formatter_]prepare_view()

问题陈述

作为一名 Drupal 开发人员,你可能遇到过这样一个场景:你需要在渲染过程中更改文本字段的值,但又不希望创建新的格式化器,或者在受影响的当前格式化器工作之前进行更改。这可以通过调用 hook_field_[formatter_]prepare_view() 挂钩来实现。

然而,直接使用此挂钩会面临两个障碍:

  • 仅支持单个模块: hook_field_formatter_info_alter() 仅允许单个模块添加到受影响的格式化器。
  • 仅适用于模块创建的字段: hook_field_prepare_view() 仅对由所涉及模块创建的字段起作用。

解决方案

幸运的是,有一个优雅的解决方案,允许你在不覆盖现有格式化器的情况下调用 hook_field_[formatter_]prepare_view()

  1. 实现 hook_field_attach_prepare_view() 此挂钩允许你在字段准备视图时对其进行修改。
  2. 使用 field_attach_prepare_view() 函数: 附加准备视图回调,它将成为 hook_field_attach_prepare_view() 实现的一部分。
  3. 在准备视图回调中修改字段值: 使用 field_get_items()field_set_items() 函数检索和设置字段的值。
  4. 确保你的模块优先执行: 通过在 .info.yml 文件中指定更高的权重,确保你的模块的更改在其他模块之前应用。

代码示例

以下代码示例演示了如何使用上述步骤:

/**
 * Implements hook_field_attach_prepare_view().
 */
function MY_MODULE_field_attach_prepare_view($field, $instance, $langcode, &$items) {
  // Retrieve the original field values.
  $original_values = field_get_items($field->entity_type, $field->entity, $field->field_name, $langcode);

  // Modify the field values.
  foreach ($items as &$item) {
    $item['value'] = strtoupper($item['value']);
  }

  // Set the modified field values.
  field_set_items($field->entity_type, $field->entity, $field->field_name, $items, $langcode);
}

总结

通过使用 hook_field_attach_prepare_view(),你可以在不覆盖现有格式化器的情况下修改文本字段值。这提供了灵活性,允许你根据需要自定义字段渲染。

常见问题解答

  1. 为什么 hook_field_formatter_info_alter() 仅接受单个模块?
    为了避免模块之间的冲突,Drupal 仅允许一个模块修改任何给定格式化器的信息。

  2. 如何确保我的模块在其他模块之前执行?
    通过在 .info.yml 文件中指定更高的 weight 值,你可以确保你的模块在模块堆栈中加载的顺序靠前。

  3. 可以同时使用 hook_field_prepare_view()hook_field_attach_prepare_view() 吗?
    可以,但 hook_field_prepare_view() 仅对模块创建的字段有效。

  4. 是否有其他方法可以在不覆盖格式化器的情况下修改字段值?
    另一个选择是使用 field_formatter_view() 函数,但它需要你手动加载格式化器。

  5. 有哪些示例用途可以使用 hook_field_attach_prepare_view()
    此挂钩可用于对文本字段进行各种修改,例如:

    • 强制文本全部大写或小写
    • 过滤或替换特定单词或短语
    • 根据访问者的语言或角色自定义字段值