如何在不覆盖现有格式化器的情况下调用 hook_field_[formatter_]prepare_view()?
2024-03-12 18:07:17
在不覆盖现有格式化器的情况下调用 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()
:
- 实现
hook_field_attach_prepare_view()
: 此挂钩允许你在字段准备视图时对其进行修改。 - 使用
field_attach_prepare_view()
函数: 附加准备视图回调,它将成为hook_field_attach_prepare_view()
实现的一部分。 - 在准备视图回调中修改字段值: 使用
field_get_items()
和field_set_items()
函数检索和设置字段的值。 - 确保你的模块优先执行: 通过在
.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()
,你可以在不覆盖现有格式化器的情况下修改文本字段值。这提供了灵活性,允许你根据需要自定义字段渲染。
常见问题解答
-
为什么
hook_field_formatter_info_alter()
仅接受单个模块?
为了避免模块之间的冲突,Drupal 仅允许一个模块修改任何给定格式化器的信息。 -
如何确保我的模块在其他模块之前执行?
通过在.info.yml
文件中指定更高的weight
值,你可以确保你的模块在模块堆栈中加载的顺序靠前。 -
可以同时使用
hook_field_prepare_view()
和hook_field_attach_prepare_view()
吗?
可以,但hook_field_prepare_view()
仅对模块创建的字段有效。 -
是否有其他方法可以在不覆盖格式化器的情况下修改字段值?
另一个选择是使用field_formatter_view()
函数,但它需要你手动加载格式化器。 -
有哪些示例用途可以使用
hook_field_attach_prepare_view()
?
此挂钩可用于对文本字段进行各种修改,例如:- 强制文本全部大写或小写
- 过滤或替换特定单词或短语
- 根据访问者的语言或角色自定义字段值