Каковы основные принципы реализации hook_menu()
?
Я хотел бы видеть основы, освещенные в одном вопросе, чтобы избежать необходимости отвечать на одни и те же похожие, но разные вопросы снова и снова.
Эта информация действительна для Drupal 6 и 7. В Drupal 8 hook_menu()
была заменена новая система маршрутизации . Ниже мы реализуем hook_menu()
в три простых шага.
Создайте пустой модуль, следуя инструкциям в разделе Как создать пустой модуль . В показанном здесь коде предполагается, что модуль называется helloworld .
Добавьте следующий код в файл модуля.
/**
* 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!';
}
Включите модуль и посетите http://example.com/hello . (Замените example.com доменным именем для вашего сервера.)
Вы должны увидеть сообщение «Hello world!». Это оно! У вас полностью рабочая hook_menu()
реализация. Далее следуют различные более сложные темы hook_menu()
. В частности, вы можете захотеть прочитать о разрешениях, так как страница выше будет доступна любому.
Если вы хотите передать больше данных обратному вызову страницы, вы можете использовать аргументы страницы для достижения этой цели. Аргументы страницы должны быть массивом аргументов для передачи обратному вызову страницы. Если в качестве аргумента используется целое число, оно будет представлять собой часть URL-адреса, начиная с 0, с однократным увеличением для каждой косой черты (/). В следующем примере это означает, что 0 будет превращен в «привет».
function helloworld_menu() {
$items['hello'] = array(
'page callback' => 'helloworld_page',
'page arguments' => array(0),
);
return $items;
}
function helloworld_page($argument1) {
return $argument1;
}
Строки будут отправлены дословно, поэтому array(0, 'world')
могут быть использованы для hello world
выхода снова.
function helloworld_page($argument1, $argument2) {
return $argument1 . ' ' . $argument2;
}
«Подстановочные знаки» могут использоваться для приема произвольных данных из URL.
function helloworld_menu() {
$items['hello/%'] = array(
'page callback' => 'helloworld_page',
'page arguments' => array(1),
);
return $items;
}
function helloworld_page($argument1) {
return $argument1;
}
Посещение привет / мир, $argument1
будет равным world
.
Часто аргументом URL будет число, идентифицирующее, например, сущность. Чтобы избежать дублирования кода, который преобразует этот идентификатор в соответствующий объект, Drupal поддерживает автозагрузку для «именованных» подстановочных знаков. Когда используется именованный шаблон, Drupal проверит функцию с тем же именем, что и шаблон, с суффиксом _load
. Если такая функция найдена, она будет вызываться со значением значения в URL, и все, что возвращается функцией-загрузчиком, будет передано обратному вызову страницы вместо исходного значения. Так как в Drupal уже есть такая функция для загрузки узлов, node_load()
мы можем автоматически загружать узлы и передавать их на обратный вызов страницы.
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));
}
Иногда необходимо автоматически загружать больше, основываясь на более чем одном аргументе. Поскольку по умолчанию в загрузчик передается только именованный аргумент, нужно явно указать Drupal, какие дополнительные аргументы загрузки следует передать загрузчику. Например, чтобы загрузить конкретную ревизию узла, необходимо перейти к node_load()
идентификатору узла и идентификатору ревизии. Это может быть достигнуто с помощью следующего кода.
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));
}
'access callback' => TRUE,
необходимо сделать простой пример выше видимым для всех, но вряд ли он идеален, так как не позволяет контролировать то, что когда-либо. Любой, кто попытается посетить / привет, получит доступ. Самый простой способ обеспечить некоторую меру контроля - это обеспечить обратный вызов доступа, очень похожий на обратный вызов страницы сверху. Следующий код по-прежнему разрешает доступ кому угодно, но показывает, как переместить логику в функцию, вызываемую во время доступа, что позволяет использовать более сложную логику.
/**
* 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;
}
Это не обязательно лучший способ, поскольку использование пользовательской функции часто приводит к ненужному дублированию кода. Большую часть времени лучше использовать user_access()
. Вместе с обратным вызовом доступа можно установить аргументы доступа. Можно потребовать, чтобы страница была доступна для просмотра пользователям с разрешением на доступ к профилям пользователя с помощью следующего кода.
/**
* 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;
}
Поскольку обратным вызовом доступа по умолчанию является user_access, его можно опустить, как в приведенном выше коде.
Официальная hook_menu()
документация предоставляет гораздо больше информации о наиболее сложных сценариях использования хука.
title
свойство требуется для всех предметов, возвращенных изhook_menu()