¿Cómo debo implementar hook_menu ()?


103

¿Cuáles son los fundamentos de la implementación hook_menu()?

Me gustaría ver los conceptos básicos cubiertos en una sola pregunta, para evitar tener que responder una y otra vez las mismas preguntas similares pero diferentes.

Respuestas:


148

Esta información es válida para Drupal 6 y 7. En Drupal 8, hook_menu()ha sido reemplazado por un nuevo sistema de enrutamiento . A continuación implementamos hook_menu()en tres simples pasos.

Paso uno

Cree un módulo vacío siguiendo las instrucciones en Cómo crear un módulo vacío . En el código que se muestra aquí, se supone que el módulo se llama helloworld .

Segundo paso

Agregue el siguiente código al archivo del módulo.

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

Paso tres

Habilite el módulo y visite http://example.com/hello . (Reemplace example.com con el nombre de dominio de su servidor).
Debería ver el mensaje "¡Hola, mundo!". ¡Eso es! Tienes una hook_menu()implementación totalmente funcional . Lo que sigue son varios temas más avanzados con respecto hook_menu(). En particular, es posible que desee leer acerca de los permisos, ya que cualquiera podrá ver la página anterior.

Argumentos

Si desea pasar más datos a la devolución de llamada de la página, puede usar argumentos de página para lograr esto. Los argumentos de la página deben ser una matriz de argumentos para pasar a la devolución de llamada de la página. Si se usa un entero como argumento, representará una parte de la URL, comenzando desde 0, incrementada una vez por cada barra inclinada (/). En el siguiente ejemplo, esto significa que el 0 se convertirá en 'hola'.

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

  return $items;
}

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

Las cadenas se enviarán literalmente, por lo que array(0, 'world')podrían usarse para hello worldsalir nuevamente.

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

Los "comodines" se pueden usar para aceptar datos arbitrarios de la URL.

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

  return $items;
}

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

Visitando hola / mundo, $argument1será igual world.

Argumento de carga automática

A menudo, un argumento de URL será el número que identifica, por ejemplo, una entidad. Para evitar duplicar el código que convierte esta ID en su objeto correspondiente, Drupal admite la carga automática de comodines "con nombre". Cuando se utiliza un comodín con nombre, Drupal buscará una función con el mismo nombre que el comodín, con el sufijo _load. Si se encuentra dicha función, se llamará con el valor del valor en la URL, y lo que devuelva la función del cargador se pasará a la devolución de llamada de la página en lugar del valor original. Dado que Drupal ya tiene dicha función para cargar nodos node_load(), podemos hacer que los nodos se carguen automáticamente y pasen a la página de devolución de llamada.

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

Carga automática avanzada

A veces, será necesario cargar automáticamente más en función de más de un argumento. Dado que solo el argumento nombrado se pasa al cargador de forma predeterminada, es necesario decirle explícitamente a Drupal qué argumentos de carga adicionales se deben pasar al cargador. Por ejemplo, para cargar una revisión específica de un nodo, es necesario pasar a node_load()una ID de nodo y una ID de revisión. Eso se puede lograr con el siguiente código.

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

Permisos

'access callback' => TRUE,es necesario para que el simple ejemplo anterior sea visible, pero no es ideal, ya que no permite ningún control. Cualquier persona que intente visitar / hola tendrá acceso. La forma más fácil de proporcionar alguna medida de control es proporcionar una devolución de llamada de acceso, al igual que la devolución de llamada de la página desde arriba. El siguiente código todavía permite el acceso a cualquier persona, pero muestra cómo mover la lógica a una función llamada en el momento de acceso, lo que permite una lógica más compleja.

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

Esta no es necesariamente la mejor manera, ya que el uso de una función personalizada a menudo duplicará innecesariamente el código. Una mejor manera será, la mayoría de las veces, usar user_access(). Juntos, la devolución de llamada de acceso es posible establecer argumentos de acceso. Es posible requerir que la página sea visible para los usuarios con el permiso de acceso a los perfiles de usuario con el siguiente código.

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

Como la devolución de llamada de acceso por defecto es user_access, puede omitirse, como en el código anterior.

Temas más avanzados

La hook_menu()documentación oficial proporciona mucha más información sobre los casos de uso más complejos para el gancho.


3
¡Increíble! Solo en aras de la integridad, la titlepropiedad se requiere para todos los artículos devueltos desdehook_menu()
Clive

1
Sé que los documentos lo dicen, pero cuando probé en D7, ese no fue el caso. Supongo que podría agregarlo al primer ejemplo, pero quería mantener las cosas al mínimo absoluto para que sea lo más fácil posible.
Letharion

1
Yo diría que agregar un título a una página es una de las cosas mínimas absolutas que podría querer hacer con hook_menu () pero es su publicación: P Sin embargo, podría valer la pena corregir los errores de sintaxis (ejemplos de código 2, 4, 5 y 6), para que la gente pueda copiar y pegar
Clive

1
Argh, inicialmente fui diligente al ejecutar el código, pero con el tiempo me volví más descuidado y comencé a copiar y pegar. Se corrigieron los errores de sintaxis, al menos los que vi;) Bueno, tienes razón en que debería haber un título, por supuesto, así que agregué uno al ejemplo inicial.
Letharion

1
¿Cómo puedo registrar un archivo php en una ruta usando hook_menu? Es un archivo php escrito personalizado que incluye drupal bootstrap, utiliza variables de sesión de drupal y acepta un argumento que es una identificación de usuario.
Елин Й.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.