Wie soll ich hook_menu () implementieren?

103

Was sind die Grundlagen der Umsetzung hook_menu()?

Ich möchte, dass die Grundlagen in einer einzigen Frage behandelt werden, um zu vermeiden, dass dieselben ähnlichen, aber unterschiedlichen Fragen immer wieder beantwortet werden müssen.

Letharion
quelle

Antworten:

148

Diese Information gilt für Drupal 6 und 7. In Drupal 8 wurde hook_menu()das Routing durch ein neues System ersetzt . Nachfolgend implementieren wir hook_menu()in drei einfachen Schritten.

Schritt eins

Erstellen Sie ein leeres Modul gemäß den Anweisungen in Wie ein leeres Modul erstellen . In dem hier gezeigten Code wird davon ausgegangen, dass das Modul helloworld heißt .

Schritt zwei

Fügen Sie der Moduldatei den folgenden Code hinzu.

/**
 * 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!';
}

Schritt drei

Aktivieren Sie das Modul und besuchen Sie http://example.com/hello . (Ersetzen Sie example.com durch den Domainnamen Ihres Servers.)
Die Meldung "Hallo Welt!" Sollte angezeigt werden . Das ist es! Sie haben eine voll funktionsfähige hook_menu()Implementierung. Im Folgenden werden verschiedene weiterführende Themen behandelt hook_menu(). Insbesondere möchten Sie möglicherweise Informationen zu Berechtigungen lesen, da die obige Seite von jedem angezeigt werden kann.

Argumente

Wenn Sie mehr Daten an den Seitenrückruf übergeben möchten, können Sie Seitenargumente verwenden, um dies zu erreichen. Seitenargumente sollten ein Array von Argumenten sein, die an den Seitenrückruf weitergeleitet werden. Wenn eine Ganzzahl als Argument verwendet wird, stellt sie einen Teil der URL dar, beginnend mit 0, und wird für jeden Schrägstrich (/) einmal erhöht. Im folgenden Beispiel bedeutet dies, dass die 0 in "Hallo" umgewandelt wird.

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

  return $items;
}

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

Strings werden wörtlich gesendet, array(0, 'world')können also verwendet werden, um hello worldwieder herauszukommen.

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

Mit "Wildcards" können beliebige Daten aus der URL übernommen werden.

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

  return $items;
}

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

Besuch Hallo / Welt, $argument1wird gleich world.

Argument Autoloading

Häufig ist ein URL-Argument die Nummer, die beispielsweise eine Entität identifiziert. Um zu vermeiden, dass Code dupliziert wird, der diese ID in das entsprechende Objekt konvertiert, unterstützt Drupal das automatische Laden von "benannten" Platzhaltern. Wenn ein benannter Platzhalter verwendet wird, sucht Drupal nach einer Funktion mit demselben Namen wie der Platzhalter mit dem Suffix "" _load. Wenn eine solche Funktion gefunden wird, wird sie mit dem Wert des Werts in der URL aufgerufen, und alles, was von der Loader-Funktion zurückgegeben wird, wird anstelle des ursprünglichen Werts an den Seitenrückruf übergeben. Da Drupal bereits über eine solche Funktion zum Laden von Knoten verfügt node_load(), können Knoten automatisch geladen und an den Seitenrückruf übergeben werden.

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

Erweitertes Autoloading

Manchmal ist es notwendig, mehr basierend auf mehr als einem Argument automatisch zu laden. Da standardmäßig nur das genannte Argument an den Loader übergeben wird, muss Drupal explizit mitgeteilt werden, welche zusätzlichen Ladeargumente an den Loader weitergegeben werden sollen. Um beispielsweise eine bestimmte Revision eines Knotens zu laden, müssen node_load()eine Knoten-ID und eine Revisions-ID übergeben werden. Dies kann durch den folgenden Code erreicht werden.

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

Berechtigungen

'access callback' => TRUE,ist notwendig, um das obige einfache Beispiel überhaupt sichtbar zu machen, aber es ist kaum ideal, da es überhaupt keine Kontrolle erlaubt. Jeder, der versucht, / hallo zu besuchen, erhält Zugang. Der einfachste Weg, um ein gewisses Maß an Kontrolle zu bieten, ist die Bereitstellung eines Zugriffsrückrufs, ähnlich wie der Seitenrückruf von oben. Der folgende Code ermöglicht weiterhin den Zugriff auf alle, zeigt jedoch, wie die Logik zu einer Funktion verschoben wird, die zum Zeitpunkt des Zugriffs aufgerufen wird, wodurch eine komplexere Logik ermöglicht wird.

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

Dies ist nicht unbedingt der beste Weg, da die Verwendung einer benutzerdefinierten Funktion Code häufig unnötig dupliziert. Ein besserer Weg wird es sein, die meiste Zeit zu verwenden user_access(). Zusammen mit dem Access Callback können Zugriffsargumente gesetzt werden. Es ist möglich, dass die Seite für Benutzer mit der Berechtigung zum Zugriff auf Benutzerprofile mit dem folgenden Code sichtbar sein muss .

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

Da der Zugriffsrückruf standardmäßig user_access lautet, kann er wie im obigen Code weggelassen werden.

Fortgeschrittenere Themen

Die offizielle hook_menu()Dokumentation enthält viel mehr Informationen zu den komplexesten Anwendungsfällen für den Hook.

Letharion
quelle
3
Genial! Der Vollständigkeit halber titlewird die Unterkunft für alle vonhook_menu()
Clive
1
Ich weiß, dass die Dokumentation dies sagt, aber als ich in D7 getestet habe, war das nicht der Fall. Ich könnte es zum ersten Beispiel hinzufügen, aber ich wollte die Dinge auf ein absolutes Minimum beschränken, um es so einfach wie möglich zu machen.
Letharion
1
Ich würde sagen, das Hinzufügen eines Titels zu einer Seite ist eines der absoluten Mindestanforderungen, die Sie mit hook_menu () erfüllen können, aber es ist Ihr Beitrag: P Könnte es wert sein, die Syntaxfehler zu beheben (Codebeispiele 2, 4, 5 & 6), damit die Leute kopieren und einfügen können
Clive
1
Argh, ich war anfangs fleißig darin, den Code tatsächlich auszuführen, aber mit der Zeit wurde ich schlampiger und fing an, Text einzufügen. Die Syntaxfehler wurden behoben, zumindest die, die ich gesehen habe;) Nun, Sie haben Recht, dass es natürlich einen Titel geben sollte , also habe ich einen zum ursprünglichen Beispiel hinzugefügt.
Letharion
1
Wie kann ich eine PHP-Datei mit hook_menu in einem Pfad registrieren? Es ist eine benutzerdefinierte PHP-Datei, die Drupal-Bootstrap enthält, Drupal-Sitzungsvariablen verwendet und ein Argument akzeptiert, das eine Benutzer-ID ist.
Елин Й.