Drupal 8:改变钩子权重
Drupal的挂钩系统允许模块与Drupal应用程序的各个部分进行交互,并且是应用程序功能的一部分。
我发现的一个常见问题是在挂钩过程中更改其他模块添加的内容。例如,可能会调用一个钩子,它涉及从一个或多个模块收集数据。如果您需要拦截此配置,则无法保证您的模块会在您尝试拦截的模块之后被调用。
另一个(更具体的)示例是更改表单时。下面的代码显示了hook_form_alter()在站点上的所有节点编辑表单上运行。
这里修改的source_language表单字段是由content_translation模块添加的,我发现它经常添加在这个钩子之后,这意味着钩子实际上什么都不做,因为source_langcode字段不存在。
这里的解决方案是使用另一个钩子来改变钩子处理器中元素的顺序,以便我们的钩子在添加这个表单元素的钩子之后被处理。所述hook_module_implements_alter()钩子用于实现此目的。
在下面的例子中,我们寻找form_alter钩子中钩子实现的存在。如果我们找到它,那么我们将它复制到数组的末尾。这具有允许我们的钩子在实现相同钩子的所有其他钩子之后运行的效果。
/** * Implements hook_module_implements_alter(). */ function my_module_module_implements_alter(&$implementations, $hook) { if ($hook == 'form_alter' && isset($implementations['my_module'])) { //将此模块的form_alter实现移动到列表的末尾。 //我们这样做是为了让my_module_form_node_page_form_alter //在ContentTranslationHandler::entityFormAlter之后调用函数 //其中包含我们试图改变的代码。 $hookInit = $implementations['my_module']; unset($implementations['my_module']); $implementations['my_module'] = $hookInit; } }另一个例子是改变hook_page_top()钩子中的page_top数组。我在这里尝试做的是删除node_preview区域的view_mode形式,因为(当时)我们不希望用户更改预览的视图类型。碰巧的是,node_preview表单已添加到hook_page_top()节点模块的钩子中,因此必须在节点模块之后运行该钩子的实现,以便正确拦截表单。
这是完整的代码。
/** * Implements hook_page_top(). */ function my_module_page_top(array &$page_top) { if (isset($page_top['page_top']['node_preview'])) { unset($page_top['page_top']['node_preview']['view_mode']); } } /** * Implements hook_module_implements_alter(). */ function my_module_module_implements_alter(&$implementations, $hook) { if ($hook == 'page_top') { //将此模块的hook_page_top实现移动到列表的末尾。 $hookInit = $implementations['my_module']; unset($implementations['my_module']); $implementations['my_module'] = $hookInit; } }