你能在 Drupal 中创建自己的 Hook 吗?

Posted

技术标签:

【中文标题】你能在 Drupal 中创建自己的 Hook 吗?【英文标题】:Can you Create your Own Hook in Drupal? 【发布时间】:2011-06-27 01:00:19 【问题描述】:

是否可以在 Drupal 模块中创建您自己的钩子以供其他 Drupal 模块使用?如果没有,Drupal 中是否有第三方开发人员提供挂钩的机制?如果到目前为止一切都不是,那么核心中的钩子列表在哪里实现?

据我了解,Drupal 模块在称为hooks 的系统之类的事件上工作。当您创建一个新模块时,您会创建实现挂钩的函数。例如,有一个 hook_delete 钩子。如果你在你的模块中实现一个函数

function mymodule_delete($node)


每当删除节点时都会调用此函数。

我想知道的是,作为第三方模块开发人员,我是否有办法创建我自己的钩子。比如说,hook_alanskickbutthook 之类的东西,以便其他模块开发人员可以订阅这个钩子。

如果这是可能的,你是怎么做到的?我查看了官方文档并没有发现太多内容,当我开始浏览 Drupal 源代码时我仍然有点头晕(我了解递归,但没有花足够的时间思考递归问题)。欢迎提供完整的解决方案,但我很高兴能指出正确的方向。

【问题讨论】:

【参考方案1】:

如果我记得...http://api.drupal.org/api/drupal/modules--node--node.api.php/function/hook_delete/7

这有帮助吗?自从我搞砸 Drupal 以来已经有一段时间了。

要创建/提供自定义 Drupal 钩子,您必须以这样的方式实现,即使用 module_invoke 或 module_invoke_all 调用钩子不会与其他模块钩子发生任何冲突。钩子的名称应该是唯一的,它应该以一种通用的方式提供所有/特定的功能,以至于它不需要对代码进行任何类型的调整。所有配置都必须在管理页面上进行,并且应该将这些配置存储在单独的表中或由 Drupal 创建的任何现有表或您的模块所依赖的模块中。钩子应该很容易被其他模块实现,并且实现起来不应该很复杂。当您创建自定义挂钩时,您的模块将充当 API 提供者。

【讨论】:

【参考方案2】:

Module_invoke_all() 是您创建自己的钩子的门票:

查看 API:

http://api.drupal.org/api/drupal/includes--module.inc/function/module_invoke_all

然后看看这篇很棒的文章:

http://web.archive.org/web/20101227170201/http://himerus.com/blog/himerus/creating-hooks-your-drupal-modules

(编辑:在http://himerus.com/blog/himerus/creating-hooks-your-drupal-modules,但现在没有了)

一旦你完成了你的钩子,就可以在另一个模块中调用它:

/**
 * Implementation of hook_myhookname()
 */

function THISMODULENAME_myhookname(args)
  //do stuff

【讨论】:

在您发布的教程中,什么叫“taxonomy_rockstar_generate_layouts”函数? (对于新手式的问题,我很抱歉。我对 Druapl 还很陌生,所以我不太清楚系统中的东西属于哪里)。 一些更正/提示:a) 使用 module_invoke_all() 时,$args 不是引用。 b)如果您想通过引用传递某些内容,请使用 drupal_alter() (在钩子名称上强制使用“_alter”后缀)或 module_implements + 循环,然后直接调用实现。 c) 推荐的记录钩子的方法是在 yourmodule.api.php 文件中,参见核心示例。 d) D7 中收集信息时的常见模式,如果使用信息后缀并在其上调用 drupal_alter。示例 . 很好地抓住了参考...我在添加它时正在考虑 drupal_alter(),已编辑 @jpstrikesback 感谢您的澄清。还有一个更明确的问题。 应该从哪里调用 module_invoke_all?我是否正确,您将实现核心模块的早期钩子之一并将其放入其中?还是别的什么? 通常你会创建一个钩子来允许另一个模块在你使用它之前修改一些数据(你也可以在你自己的模块中使用这个钩子)。在这种情况下,我会在处理数据之前放置 module_invoke_all()。例如查看drupal_goto,然后查看Here is another good tutorial/example。【参考方案3】:

例如,假设您想创建 hook_my_custom_goodness() 供其他人使用。然后只需将这样的代码放在模块中您希望钩子发生的位置:

$variables['msg'] = 'foo';

// Make sure at least one module implements our hook.
if (sizeof(module_implements('my_custom_goodness')) > 0) 
  // Call modules that implement the hook, and let them change $variables.
  $variables = module_invoke_all('my_custom_goodness', $variables);


drupal_set_message($variables['msg']); // Will display 'bar' instead.

现在,如果有人想使用你的钩子,那么他们可以在自己的模块中这样做:

/**
 * Implements hook_my_custom_goodness().
 */
function SOME_OTHER_MODULE_my_custom_goodness($variables) 
  $variables['msg'] = 'bar';
  return $variables;

这里有更完整的解释:

http://tylerfrankenstein.com/code/drupal-create-custom-hook-for-other-modules

【讨论】:

【参考方案4】:

对于 Drupal 6 和 7,drupal_alter() 可能是最好的选择。

如the module_invoke_all() documentation中所述,

所有参数都按值传递。如果需要,请使用 drupal_alter() 通过引用传递参数。

在 Drupal 8 中,使用 ModuleHandler::alter。

将可变变量传递给特定的 hook_TYPE_alter() 实现。

【讨论】:

以上是关于你能在 Drupal 中创建自己的 Hook 吗?的主要内容,如果未能解决你的问题,请参考以下文章

你能在 Swift 中创建匿名内部类吗?

Git:你能在master改变后更新分支吗?

在 Drupal 中创建组结构

你能在不同的线程上调用相同的方法吗?

在Drupal中创建一个Context View,然后根据NID(node id)显示在Panel中

在android中创建自己的动作栏