web-dev-qa-db-fra.com

Comment dois-je implémenter hook_menu ()?

Quels sont les principes fondamentaux de l'implémentation de hook_menu()?

Je voudrais voir les bases abordées dans une seule question, pour éviter d'avoir à répondre aux mêmes questions similaires mais différentes encore et encore.

102
Letharion

Ces informations sont valables pour Drupal 6 et 7. Dans Drupal 8, hook_menu() a été remplacé par nouveau système de routage . Ci-dessous, nous implémentons hook_menu() en trois étapes simples.

La première étape

Créez un module vide en suivant les instructions de Comment créer un module vide . Dans le code montré ici, on suppose que le module est nommé helloworld .

Deuxième étape

Ajoutez le code suivant au fichier de module.

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

Troisième étape

Activez le module et visitez http://example.com/hello . (Remplacez example.com par le nom de domaine de votre serveur.)
Vous devriez voir le message "Bonjour tout le monde!". C'est ça! Vous disposez d'une implémentation hook_menu() pleinement opérationnelle. Ce qui suit sont divers sujets plus avancés concernant hook_menu(). En particulier, vous voudrez peut-être en savoir plus sur les autorisations, car la page ci-dessus sera visible par n'importe qui.

Arguments

Si vous souhaitez transmettre davantage de données au rappel de page, vous pouvez utiliser des arguments de page pour y parvenir. Les arguments de page doivent être un tableau d'arguments à transmettre au rappel de page. Si un entier est utilisé comme argument, il représentera une partie de l'URL, à partir de 0, incrémentée une fois pour chaque barre oblique (/). Dans l'exemple suivant, cela signifie que le 0 sera transformé en "bonjour".

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

  return $items;
}

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

Les chaînes seront envoyées textuellement, donc array(0, 'world') pourrait être utilisé pour sortir hello world À nouveau.

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

Les "caractères génériques" peuvent être utilisés pour accepter des données arbitraires de l'URL.

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

  return $items;
}

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

En visitant hello/world, $argument1 Sera égal à world.

Chargement automatique des arguments

Souvent, un argument URL sera le numéro identifiant, par exemple, une entité. Pour éviter la duplication du code qui convertit cet ID en son objet correspondant, Drupal prend en charge le chargement automatique pour les caractères génériques "nommés". Lorsqu'un caractère générique nommé est utilisé, Drupal vérifie pour une fonction portant le même nom que le caractère générique, suffixée par _load. Si une telle fonction est trouvée, elle sera appelée avec la valeur de la valeur dans l'URL, et tout ce qui sera retourné par la fonction de chargeur sera être passé au rappel de page à la place de la valeur d'origine. Puisque Drupal a déjà une telle fonction pour charger les nœuds, node_load() , nous pouvons obtenir les nœuds chargés automatiquement et passés au rappel de page.

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

Chargement automatique avancé

Parfois, il sera nécessaire de charger automatiquement plus en fonction de plusieurs arguments. Étant donné que seul l'argument nommé est transmis au chargeur par défaut, il faut indiquer explicitement Drupal quels arguments de chargement supplémentaires doivent être transmis au chargeur. Par exemple, pour charger une révision spécifique d'un nœud, il est nécessaire de passer à node_load() un ID de nœud et un ID de révision. Cela peut être accompli par le code suivant.

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

Autorisations

'access callback' => TRUE, Est nécessaire pour rendre le simple exemple ci-dessus visible, mais ce n'est pas idéal, car il ne permet aucun contrôle. Quiconque essaie de visiter/bonjour se verra accorder l'accès. Le moyen le plus simple de fournir une certaine mesure de contrôle consiste à fournir un rappel d'accès, un peu comme le rappel de page ci-dessus. Le code suivant permet toujours d'accéder à n'importe qui, mais montre comment déplacer la logique vers une fonction appelée au moment de l'accès, permettant ainsi une logique plus complexe.

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

Ce n'est pas nécessairement le meilleur moyen, car l'utilisation d'une fonction personnalisée dupliquera souvent inutilement du code. Une meilleure façon sera, la plupart du temps, d'utiliser user_access() . Ensemble, le rappel d'accès, il est possible de définir des arguments d'accès. Il est possible d'exiger que la page soit visible par les utilisateurs avec l'autorisation d'accéder aux profils utilisateur avec le code suivant.

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

Étant donné que le rappel d'accès par défaut est user_access, il peut être omis, comme dans le code ci-dessus.

Sujets plus avancés

La documentation officielle hook_menu() fournit beaucoup plus d'informations sur les cas d'utilisation les plus complexes pour le hook.

147
Letharion