相互作用しないフック間でデータを渡すにはどうすればよいですか?


10

相互に作用しないフック間、またはメニューコールバックとフック間でデータを渡すにはどうすればよいですか?

2つのフックに共通のパラメーターがあり、そのパラメーターが参照によって渡される場合、それは簡単です。フック、またはメニューコールバックとフックが共通のパラメーターを取得しない場合はどうすればよいですか?

回答:


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

@therobyouknowは、「変数のセット全体が毎回読み込まれるという事実により、多くのリクエストを処理するサイトの場合」変数テーブルであり、静的変数ではありません。これは完全に異なるものです。静的変数自体のパフォーマンスへの影響はごくわずかです。変数テーブルでも、問題を引き起こすためにシステムを乱用する必要があります。Economist.comは1時間で数十万ヒットを簡単に得ることができ、そのすべてが変数テーブルをロードします。変数は問題ではありませんが、もちろん、各変数には小さな情報のみを保存します。
Letharion 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.