Jak powinienem zaimplementować hook_menu ()?

103

Jakie są podstawy wdrożenia hook_menu()?

Chciałbym zobaczyć podstawy omówione w jednym pytaniu, aby uniknąć konieczności ciągłego odpowiadania na te same podobne, ale różne pytania.

Letharion
źródło

Odpowiedzi:

148

Ta informacja dotyczy Drupala 6 i 7. W Drupal 8 hook_menu()został zastąpiony nowym systemem routingu . Poniżej wdrażamy hook_menu()w trzech prostych krokach.

Krok pierwszy

Utwórz pusty moduł, postępując zgodnie z instrukcjami w Jak utworzyć pusty moduł . W pokazanym tu kodzie przyjęto, że moduł nazywa się helloworld .

Krok drugi

Dodaj następujący kod do pliku modułu.

/**
 * Implements hook_menu().
 */
function helloworld_menu() {
  $items['hello'] = array(
    'title' => 'Hello world!',
    'page callback' => 'helloworld_page',
    'access callback' => TRUE,
  );

  return $items;
}

/**
 * Page callback for /hello.
 */
function helloworld_page() {
  return 'Hello world!';
}

Krok trzeci

Włącz moduł i odwiedź http://example.com/hello . (Zastąp example.com nazwą domeny swojego serwera.)
Powinieneś zobaczyć komunikat „Witaj świecie!”. Otóż ​​to! Masz w pełni działającą hook_menu()implementację. Poniżej znajdują się różne bardziej zaawansowane tematy dotyczące hook_menu(). W szczególności możesz przeczytać o uprawnieniach, ponieważ powyższa strona będzie widoczna dla każdego.

Argumenty

Jeśli chcesz przekazać więcej danych do wywołania zwrotnego strony, możesz w tym celu użyć argumentów strony. Argumenty strony powinny być tablicą argumentów, które należy przekazać do wywołania zwrotnego strony. Jeśli jako argument zostanie użyta liczba całkowita, będzie ona reprezentować część adresu URL, zaczynając od 0, zwiększaną raz dla każdego ukośnika (/). W poniższym przykładzie oznacza to, że 0 zostanie zmienione na „cześć”.

function helloworld_menu() {
  $items['hello'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(0),
  );

  return $items;
}

function helloworld_page($argument1) {
  return $argument1;
}

Ciągi będą wysyłane dosłownie, więc array(0, 'world')mogą zostać wykorzystane do hello worldponownego wyjścia.

function helloworld_page($argument1, $argument2) {
  return $argument1 . ' ' . $argument2;
}

Za pomocą „symboli wieloznacznych” można akceptować dowolne dane z adresu URL.

function helloworld_menu() {
  $items['hello/%'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(1),
  );

  return $items;
}

function helloworld_page($argument1) {
  return $argument1;
}

Odwiedzanie hello / world $argument1będzie równe world.

Automatyczne ładowanie argumentów

Często argumentem adresu URL jest liczba identyfikująca na przykład jednostkę. Aby uniknąć powielania kodu, który konwertuje ten identyfikator na odpowiedni obiekt, Drupal obsługuje automatyczne ładowanie dla „nazwanych” symboli wieloznacznych. Gdy użyje się nazwanego symbolu wieloznacznego, Drupal sprawdzi funkcję o tej samej nazwie co symbol wieloznaczny, z przyrostkiem _load. Jeśli taka funkcja zostanie znaleziona, zostanie wywołana z wartością wartości w adresie URL, a wszystko, co zostanie zwrócone przez funkcję modułu ładującego, zostanie przekazane do wywołania zwrotnego strony zamiast wartości oryginalnej. Ponieważ Drupal ma już taką funkcję do ładowania węzłów node_load(), możemy pobrać węzły automatycznie ładowane i przekazywane do wywołania zwrotnego strony.

function helloworld_menu() {
  $items['hello/%node'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(1),
  );

  return $items;
}

function helloworld_page($node) {
  return t('Hello node (ID = !nid)', array('!nid' => $node->nid));
}

Zaawansowane automatyczne ładowanie

Czasami konieczne będzie automatyczne ładowanie więcej na podstawie więcej niż jednego argumentu. Ponieważ domyślnie do modułu ładującego przekazywany jest tylko nazwany argument, należy wyraźnie powiedzieć Drupalowi, które dodatkowe argumenty obciążenia powinny zostać przekazane do modułu ładującego. Na przykład, aby załadować konkretną wersję węzła, konieczne jest przekazanie jej do node_load()identyfikatora węzła i identyfikatora wersji. Można to zrobić za pomocą następującego kodu.

function helloworld_menu() {
  $items['hello/%node/revision/%'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(1),
    'load arguments' => array(3),
  );

  return $items;
}

function helloworld_page($node) {
  return t('Hello node (ID = !nid, revision ID = !rid)', array('!nid' => $node->nid, '!rid' => $node->vid));
}

Uprawnienia

'access callback' => TRUE,jest konieczny, aby w ogóle można było zobaczyć powyższy prosty przykład, ale nie jest on idealny, ponieważ nie pozwala na to, aby tak się stało. Każdy, kto spróbuje odwiedzić / hello, uzyska dostęp. Najłatwiejszym sposobem zapewnienia pewnej kontroli jest zapewnienie wywołania zwrotnego dostępu, podobnie jak wywołanie zwrotne strony z góry. Poniższy kod nadal umożliwia dostęp każdemu, ale pokazuje, jak przenieść logikę do funkcji wywoływanej w czasie dostępu, umożliwiając w ten sposób bardziej złożoną logikę.

/**
 * Implements hook_menu().
 */
function helloworld_menu() {
  $items['hello'] = array(
    'page callback' => 'helloworld_page',
    'access callback' => 'helloworld_access',
  );

  return $items;
}

/**
 * Access callback for /hello.
 */
function helloworld_access() {
  return TRUE;
}

To niekoniecznie najlepszy sposób, ponieważ użycie funkcji niestandardowej często niepotrzebnie powiela kod. Lepszym sposobem będzie użycie przez większość czasu user_access(). Razem wywołanie zwrotne dostępu można ustawić argumenty dostępu. Możliwe jest, aby strona była widoczna dla użytkowników z uprawnieniami dostępu do profili użytkowników za pomocą następującego kodu.

/**
 * Implements hook_menu().
 */
function helloworld_menu() {
  $items['hello'] = array(
    'page callback' => 'helloworld_page',
    'access callback' => 'user_access',
    'access arguments' => array('access user profiles'),
  );

  return $items;
}

Ponieważ wywołanie zwrotne dostępu domyślnie to user_access, można je pominąć, jak w powyższym kodzie.

Bardziej zaawansowane tematy

Oficjalna hook_menu()dokumentacja zawiera znacznie więcej informacji na temat najbardziej złożonych przypadków użycia haka.

Letharion
źródło
3
Niesamowite! Ze względu na kompletność, titlewłaściwość jest wymagana dla wszystkich przedmiotów zwróconych zhook_menu()
Clive
1
Wiem, że tak mówią doktorzy, ale kiedy testowałem w D7, tak nie było. Myślę, że mógłbym dodać to do pierwszego przykładu, ale chciałem ograniczyć rzeczy do absolutnego minimum, aby było to tak proste, jak to możliwe.
Letharion
1
Powiedziałbym, że dodanie tytułu do strony jest jedną z absolutnie minimalnych rzeczy, które możesz zrobić z hook_menu (), ale to twój post: P Może warto naprawić błędy składniowe (przykłady kodu 2, 4, 5 i 6), aby ludzie mogli kopiować i wklejać
Clive
1
Argh, początkowo starałem się uruchomić kod, ale z biegiem czasu zrobiłem się niechlujny i zacząłem kopiować. Naprawiłem błędy składniowe, przynajmniej te, które widziałem;) Cóż, masz rację, że powinien istnieć tytuł, więc dodałem go do początkowego przykładu.
Letharion
1
Jak mogę zarejestrować plik php do ścieżki za pomocą hook_menu? Jest to niestandardowy napisany plik php, który zawiera bootstrap drupal, używa zmiennych sesji drupal i akceptuje argument, który jest identyfikatorem użytkownika.
Елин Й.