Рассмотрим кусок меню на обычном сайте.
Пока все стандартно. Теперь мы хотим, чтобы когда пользователь нажимает на меню Компания ему открывалась страница О компании.
Неправильное решение
Можно попытаться присвоить пункту Компания тот же самый адрес node/45. Пользователь делает клик на Компания .. И тут мы обнаруживаем интересную особенность Друпала. Из двух пунктов меню с одинаковыми адресами активным (class="active") Друпал сделает только один - первый по списку. Кроме того, если вы играетесь с модулем Custom Breadcrumbs - вы получите неверные хлебные крошки.
Дальше у нас есть выбор - сдаться и сделать для пункта меню Компания отдельную нормальную страницу. Либо включить хитрость и сделать страницу-редиректор которая бы перекидывала пользователя с Компания на О компании.
Как не надо делать
Начитавшись Drupal API у вас может возникнуть "гениальная" идея. Создаем новый тип материала, например, fake_page, делаем новую ноду этого типа и в ней пишем
<?php
drupal_goto('node/45');
?>
Плюсов у этого решения нет, одни недостатки:
- Внезапно отваливается индексация поиска. И вообще весь крон. В watchdog вы увидите сообщение "Cron run exceeded the time limit and was aborted.", хотя сам крон отрабатывается мгновенно. Через некоторое время (большое?
вы обнаружите, что крон умирает именно в модуле search. И именно на ноде-редиректоре.
- Человек, пришедший после вас, при попытка посмотреть содержимое fake_page будет попадать в другое место и долго удивляться что за фигня.
Правильное решение
Существует прекрасный модуль Path redirect, который в явном виде позволяет задать переадресацию с одного адреса на другой. А с помощью расово верного патча он позволяет делать переадресацию с уже существующего пути в любое другое место. Почему с уже существующего? Потому что Друпал не позволит создать пункт меню Компания с пустым адресом.
Теперь о том, где взять "уже существующий путь". По прежнему мы можем создавать пустые ноды типа fake_page, делать им красивые алиасы и адреса этих нод указывать в качестве путей для меню. Но мне этот подход не нравится тем, что эти пустые ноды будут болтаться в списке контента.
Другой подход - следуя модному в стране тренду, сделать наномодуль ;). Который только тем и будет заниматься, что объявлять нужный нам адрес существующим. Далее пример такого модуля:
nanofake.info
description = Emulates fake addresses
core = 6.x
nanofake.module
function nanofake_menu() {
$items['fake1'] = array(
'page callback' => 'nanofake_none',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
function nanofake_none() {
return '';
}
Теперь для пункта меню мы можем указать fake1 в качестве path, а в path redirector сделать перенаправление с fake1 на node/45.
Все это конечно только мой опыт (вполне возможно это все велосипед) и если у кого-то есть опыт более позитивный - прошу в комментарии.
Вложение | Размер |
---|---|
![]() | 6.44 КБ |
![]() | 592 байта |
Комментарии
Как замену pathredirect патченного, можно использовать модуль Rules.
О! Спасибо!
Только к rules нужено будет ещё pathrules добавить
В ядре такое делается так(пример из модуля block):
<?php
function block_menu() {
$items['admin/build/block'] = array(
'title' => 'Blocks',
'description' => 'Configure what block content appears in your site\'s sidebars and other regions.',
'page callback' => 'block_admin_display',
'access arguments' => array('administer blocks'),
'file' => 'block.admin.inc',
);
$items['admin/build/block/list'] = array(
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
?>
, т.е. используется тип меню MENU_DEFAULT_LOCAL_TASK - вкладки
Я использовал ссылку на одну и ту же страницу у пункта меню и его подпункта. Они оба получили класс active. Drupal 6.16
Не пойму в чем может быть "неправильность" такого подхода.
Редиректы, кстати, то-же не есть гуд.
Если уж кровь из носа нужна другая страница с тем же содержанием, то я бы использовал:
<?php
$node = node_load($nid);
print node_view($node, FALSE, TRUE);
?>
На мой взгляд это как то лучше чем городить огород из псевдо-модулей и псевдо-алиасов.
Плохое решение, поисковикам не понравится.
ИМХО, лучшее решение будет special_menu_items и через него создать пункт без ссылки.
Кстати это наилучший метод. Я использую преимущественно его.
А menu_firstchild не подойдёт?
А если так?
<?php
header('Location: ' . url('node/60'));
?>
Я сомневаюсь что так пойдет.
Скорее всего Вы получите сообщение, что хедеры уже отправлены.
Просто если хоть один байт контента уже ушел, то хедеры отправлять низя.
Я знаю, но работает
а drupal_goto думаешь чем занимается? (У ТС в разделе "Как не надо делать")
+1
Сделано специально для этого