如何在不交互的钩子之间传递数据?


10

如何在钩子之间或菜单回调与钩子之间不交互的钩子之间传递数据?

如果两个钩子有一个共同的参数,并且该参数通过引用传递,那很容易。当挂钩,菜单回调和挂钩没有共同的参数时,我该怎么办?

Answers:


12

在Drupal 7或更高版本中,请使用通过drupal_static()处理的静态变量。
drupal_static()是处理静态变量中央存储的函数。与使用static关键字声明的变量不同,用来处理的静态变量drupal_static()可以从每个函数访问。这是可能的,因为drupal_static()通过引用返回变量的内容,从而允许每个函数对其进行更改。

假设您需要在菜单处理程序和hook_block_view()的实现之间传递一个值;您可以使用以下代码。

function mymodule_menu() {
  return array('path/%' => array(
    'page callback' => 'mymodule_callback_function',
    'page arguments' => array(1),
  ));
}

function mymodule_callback_function($data) {
  $data_passer = &drupal_static('mymodule_block_data');

  $data_passer = $data;

  // Other logic specific to this page callback.
}

function mymodule_block_view($delta = '') {
  // $data_passer will now contain the value of $data, from above.
  $data_passer = &drupal_static('mymodule_block_data');

  // Change the block content basing on the content of $data_passer.
}

如果需要更频繁地访问数据,则应使用静态本地变量,该变量应包含从返回的值drupal_static()。由于只能从文字值初始化静态变量,并且不能将静态变量分配给引用,因此唯一的工作代码类似于以下代码。(此代码来自user_access()。)

  // Use the advanced drupal_static() pattern, since this is called very often.
  static $drupal_static_fast;
  if (!isset($drupal_static_fast)) {
    $drupal_static_fast['perm'] = &drupal_static(__FUNCTION__);
  }
  $perm = &$drupal_static_fast['perm'];

drupal_static()每次Drupal引导时都会重置从返回的值;如果需要在不同页面之间保留的值,则需要使用数据库表来存储该值,或者使用variable_get() / variable_set()

Drupal 6没有实现drupal_static(),但是您可以将其代码复制到您自己的模块中定义的函数中。

function &mymodule_static($name, $default_value = NULL, $reset = FALSE) {
  static $data = array(), $default = array();

  // First check if dealing with a previously defined static variable.
  if (isset($data[$name]) || array_key_exists($name, $data)) {
    // Non-NULL $name and both $data[$name] and $default[$name] statics exist.
    if ($reset) {
      // Reset pre-existing static variable to its default value.
      $data[$name] = $default[$name];
    }
    return $data[$name];
  }

  // Neither $data[$name] nor $default[$name] static variables exist.
  if (isset($name)) {
    if ($reset) {
      // Reset was called before a default is set and yet a variable must be
      // returned.
      return $data;
    }
    // First call with new non-NULL $name. Initialize a new static variable.
    $default[$name] = $data[$name] = $default_value;
    return $data[$name];
  }

  // Reset all: ($name == NULL). This needs to be done one at a time so that
  // references returned by earlier invocations of drupal_static() also get
  // reset.
  foreach ($default as $name => $value) {
    $data[$name] = $value;
  }

  // As the function returns a reference, the return should always be a
  // variable.
  return $data;
}

在使用静态变量drupal_static()(或在模块中定义的向后移植功能)之前,应牢记以下注意事项:

  • 仅当设置静态变量的代码在获得其值的代码之前运行时,该代码才起作用。如果执行顺序不合理,则该代码将无效。如果在Drupal文档中没有明确定义执行顺序,则可能会在以后的Drupal版本中更改顺序。检查您要为其执行代码的Drupal版本中执行顺序是否不变。
  • Drupal可能已经实现了一种机制,可以在不同的钩子之间共享数据。例如,在hook_form_alter()的实现不同的情况下,每个实现都可以hook_form_alter()使用$form_state; 与其他实现共享数据。以相同的方式,表单验证处理程序和表单提交处理程序可以使用$form_state通过引用传递的参数共享数据。在实施自己的代码之前,请验证是否可以使用Drupal针对特定情况已经实施的其他机制共享数据。

非常感谢您对原始海报的回答。但是我担心的是,有人告诉我,使用drupal静态变量不能很好地扩展-对于处理大量请求的网站,由于事实是每次会话,每次会话(或类似的东西)都会加载整个变量集一位同事正在告诉我这一点,他一直在从事与此相关的性能问题。你怎么看?他们建议使用Drupal缓存是传递变量的更好方法(假设目标代码接收到数据后不需要它们)
therobyouknow 2014年

@therobyouknow“对于处理大量请求的站点,由于每次都会加载整个变量集这一事实”是变量,而不是任何静态变量,这是完全不同的事情。静态变量本身对性能的影响可忽略不计。即使在变量表中,您也必须大量滥用系统才能引起问题。在一个小时内,Economist.com可以轻松获得几次10万次匹配,所有这些匹配都会加载变量表。变量不是问题,但是当然,我们在每个变量中只存储少量信息。
Letharion 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.