Jak przesyłać dane między zaczepami, które nie wchodzą w interakcje?

10

Jak przesyłać dane między zaczepami, które nie wchodzą w interakcje między nimi, lub między wywołaniem zwrotnym menu a zaczepem?

W przypadku, gdy dwa haki mają wspólny parametr, a ten parametr jest przekazywany przez odniesienie, to jest łatwe. Co mam zrobić, gdy zaczepy lub wywołanie zwrotne menu i zaczep nie otrzymują wspólnego parametru?

Letharion
źródło

Odpowiedzi:

12

W Drupal 7 lub nowszym użyj zmiennej statycznej obsługiwanej przez drupal_static () .
drupal_static()jest funkcją, która obsługuje centralne przechowywanie zmiennych statycznych. W odróżnieniu od zmiennych zadeklarowanych za pomocą staticsłowa kluczowego obsługiwane zmienne statyczne drupal_static()są dostępne z każdej funkcji; jest to możliwe, ponieważ drupal_static()zwraca treść zmiennej przez odwołanie, umożliwiając każdej funkcji jej zmianę.

Załóżmy, że trzeba przekazać wartość między obsługi menu, a następnie wdrożenie hook_block_view () ; możesz użyć następującego kodu.

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.
}

W przypadku, gdy dane wymagają częstszego dostępu, należy użyć statycznej zmiennej lokalnej, która zawierałaby zwracaną wartość drupal_static(). Ponieważ zmienne statyczne można inicjalizować tylko z wartości literalnej , a zmiennych statycznych nie można przypisywać do odwołań , jedyny działający kod jest podobny do następującego. (Ten kod pochodzi z 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'];

Wartość zwracana z drupal_static()jest resetowana za każdym razem, gdy ładuje się Drupal; jeśli potrzebujesz wartości, która jest zachowywana między różnymi stronami, musisz użyć tabeli bazy danych do przechowywania wartości lub użyj zmiennej_get () / zmienna_zestaw () .

Drupal 6 nie implementuje drupal_static(), ale możesz skopiować jego kod w funkcji zdefiniowanej we własnym module.

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;
}

Przed użyciem zmiennej statycznej z drupal_static()(lub funkcją cofnięcia portu zdefiniowaną w module) należy pamiętać o następujących kwestiach:

  • Kod działa tylko wtedy, gdy kod ustawiający zmienną statyczną działa przed kodem, aby uzyskać jego wartość; jeśli kolejność wykonywania nie jest myśląca, kod nie działa. Gdy kolejność wykonywania nie jest jasno zdefiniowana w dokumentacji Drupala, istnieje ryzyko, że kolejność zmieni się w przyszłych wersjach Drupala; sprawdź, czy kolejność wykonywania nie zmienia się w wersji Drupal, dla której implementujesz swój kod.
  • Drupal mógł wdrożyć mechanizm współdzielenia danych między różnymi zaczepami. Na przykład, w przypadku różnych implementacji hook_form_alter () , każda implementacja może współdzielić dane z innymi hook_form_alter()implementacjami za pomocą $form_state; w ten sam sposób procedury obsługi sprawdzania poprawności formularzy i procedury obsługi przesyłania formularzy mogą udostępniać dane przy użyciu $form_stateparametru przekazywanego przez odwołanie. Przed wdrożeniem własnego kodu sprawdź, czy możliwe jest udostępnianie danych przy użyciu innego mechanizmu już wdrożonego przez Drupal w konkretnym przypadku.
kiamlaluno
źródło
Naprawdę doceniam odpowiedź podaną tutaj na oryginalny plakat. Jednak obawiam się, że powiedziano mi, że używanie zmiennych statycznych drupal nie skaluje się zbyt dobrze - w przypadku witryn obsługujących wiele żądań, z uwagi na fakt, że cały zestaw zmiennych jest ładowany za każdym razem, dla każdej sesji (lub coś w tym rodzaju tego). Powiedziano mi o tym kolega, który pracował nad związanym z tym problemem związanym z wydajnością. Co myślisz? Doradzili, że użycie pamięci podręcznej Drupal byłoby lepszym sposobem przekazywania zmiennych (zakładając, że nie są one potrzebne po otrzymaniu danych przez kod docelowy)
therobyouknow
@therobyouknow „dla witryn obsługujących wiele żądań, ponieważ za każdym razem ładowany jest cały zestaw zmiennych” to tabela zmiennych , a nie jakakolwiek zmienna statyczna, co jest zupełnie inną rzeczą. Same zmienne statyczne mają znikomy wpływ na wydajność. Nawet w tabeli zmiennych musiałbyś bardzo nadużywać system, aby powodować problemy. Economist.com może z łatwością uzyskać kilka 100 000 trafień w ciągu godziny, z których wszystkie ładują tabelę zmiennych. Zmienne nie są problemem, ale oczywiście przechowujemy tylko małe informacje w każdej zmiennej.
Letharion