Был у меня тут недавно случай. Нужно было сделать каталог. Причем для каталога выдвигалось 3-а основных требования.
- Простота в управлении (а именно автоматическое создание меню)
- Неограниченный уровень вложенности
- Вывод подчиненного материала (node) на странице родителя в виде таблицы с картинками.
Искал решение, даже ветку завел Book, Node Hierarchy что еще позволяет делать иерархию? , попробовал category который глючный и сложный для простого обывателя. В итоге пришел к выводу, что по управляемости стандартный book самый простой (генерирует меню автоматически), и каталог слепить можно. Да только вот беда, в book нельзя сделать вывод тизеров материала, а можно выводить лишь названия подчиненного материала. Но разве для drupal это проблема? Конечно нет.
Решение:
Для начала снабдим нашу страницу подшивки изображением. В этотм нам поможет CCK и его доп. модуль imagefield. Ну и contemplate нам понадобится для красивого оформления этого дела. Работу с данными инструментами описывать не буду, т.к. на форуме и так много всего про них сказано. Будем считать что у нас в странице подшивки есть поле изображения
Лезем в код нашего любимого модуля book и ищем там все функции со словом theme_. Находим 3-и функции.
theme_book_navigation($node)
theme_book_export_html($title, $content)
theme_book_admin_table($form)
Ну и как Вы думаете какая нам нужна? Конечно theme_book_navigation($node). Так что берем и смело копируем её в template.php.
function theme_book_navigation($node) {
$output = '';
$links = '';
if ($node->nid) {
$tree = book_tree($node->nid); // получает меню навигации
// генерирует массив ссылок (те что в node.tpl.php $links)
if ($prev = book_prev($node)) {
drupal_add_link(array('rel' => 'prev', 'href' => url('node/'. $prev->nid)));
$links .= l(t('‹ ') . $prev->title, 'node/'. $prev->nid, array('class' => 'page-previous', 'title' => t('Go to previous page')));
}
if ($node->parent) {
drupal_add_link(array('rel' => 'up', 'href' => url('node/'. $node->parent)));
$links .= l(t('up'), 'node/'. $node->parent, array('class' => 'page-up', 'title' => t('Go to parent page')));
}
if ($next = book_next($node)) {
drupal_add_link(array('rel' => 'next', 'href' => url('node/'. $next->nid)));
$links .= l($next->title . t(' ›'), 'node/'. $next->nid, array('class' => 'page-next', 'title' => t('Go to next page')));
}
if (isset($tree) || isset($links)) {
$output = '
';
}
}
return $output;
}
?>
Как видите это еще не решение проблемы, т.к. содержание навигации создается не theme_book_navigation а book_tree($node->nid). Собственно все ясно. Нам нужно написать свою book_tree которая будет возвращать не только ссылки но и картинки например.
Для того чтобы посмотреть код booktree можно опять таки взглянуть в код модуля.
Ого оказывается что она состоит еще из одной функции book_tree_recurse. Не слишком ли много функций? Для нашей задачи хватит вполне 2-х функций расположенных в template.php. В book_tree есть функция которая рекурсивно обходит книгу в поиске её детей для создания навигации.
Именно её мы и заменим на свою сама же book_tree для нашей задачи особо не нужна
Ниже уже готовый для моего случая код с некоторым комментариями.
function combustion_book_navigation($node) {
$output = '';
if ($node->nid) {
//$tree = book_tree($node->nid);
// Код ниже взят из book_tree
$depth = 3;
$prnt = $node->nid;
$result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.status = 1 ORDER BY b.weight, n.title'));
while ($node = db_fetch_object($result)) {
$list = isset($children[$node->parent]) ? $children[$node->parent] : array();
$list[] = $node;
$children[$node->parent] = $list;
}
// наша функция, аналог book_tree_recurse
$tree = my_tree_recurse($prnt, $depth, $children, $unfold = array());
if (isset($tree)) {
$output .= '
';
}
}
return $output;
}
//$td это счетчие тегов
function my_tree_recurse($nid, $depth, $children, $unfold = array(), $td = 0) {
$output = '';
if ($depth > 0) {
if (isset($children[$nid])) {
foreach ($children[$nid] as $foo => $node) {
if ($td == 0) $output .= '
$td++;
$output .= "
if (in_array($node->nid, $unfold)) {
if ($tree = my_tree_recurse($node->nid, $depth - 1, $children, $unfold)) {
$output .= '
$output .= l($node->title, 'node/'. $node->nid);
$output .= '
';
$output .= '
';
}
else {
$output .= '
';
}
}
else {
// если есть вложенная структура
if ($tree = my_tree_recurse($node->nid, 1, $children)) {
// node_load считаю достаточно ресурсоемкой функцией. тут больше для примера
$nd = node_load($node->nid);
// field_[0]['filename'] можно посмотреть как называется
// ваш массив в contemplate
$output .= "nid."'>field_[0]['filename']."'/>";
$output .= "
".l($nd->title, 'node/'. $nd->nid)."
";
$output .= "".$nd->teaser."";
}
else {
// если последние дети
$nd = node_load($node->nid);
$output .= "nid."'>field_[0]['filename']."'/>";
$output .= "
".l($nd->title, 'node/'. $nd->nid)."
";
$output .= "".$nd->teaser."";
}
}
// вывод в 3-и колонки
$output .= "
";
if ($td == 3) {
$output .= '
';
$td = 0;
}
}
}
}
return $output;
}
?>
__________________________
Bite my shiny, metal ass!
Комментарии
Спасибо! А посмотреть в действии можно?
пока нет. все на стадии тестирования заказчиком. А что смотреть? Не верите?
"Неограниченный уровень вложенности"
Насколько я понимаю в Друпал 6 есть ограничение на количество вложенности для модуля Book (9 уровней). В Друпал. 5 такого не было. Но я не проверял предел вложенности.
Я если честно тоже не проверял. Думал что для 5-ки он не ограничен. Ну кто знает, тот напишет думаю.
Для 5ки вложенность не ограничена - в 6ке есть ограничение.
Подскажите, пожалуйста, как мне в Друпал 6 вывести развернутый список всей иерархии книг на одной странице?
Я сделал для Друпал 5: http://drupal.ru/book/toc
Но для Друпал 6 всё поменялось...
неуверен, но может поможет http://api.drupal.org/api/file/modules/book/book-all-books-block.tpl.php...
Покрайне мере пишут что в блоке можно вывести всё меню.
К сожалению уже больше месяца в 6-ку не ногой. некогда.
Запомним, спасибо.
Попробовал сделать по описанию - вылезает ошибка:
Fatal error: Cannot redeclare theme_book_navigation() (previously declared in Z:\home\new\www\modules\book\book.module:481) in Z:\home\new\www\themes\garland\template.php on line 125
вместо дословного theme_book_navigation() необходимо theme заменить на имя вашей темы. Для garland это garland.
А все точно по описанию сделали? Для начала скопируйте код просто
<?php
garland_book_navigation() {
return "IT WORKS!";
}
?>
в Z:\home\new\www\themes\garland\template.php И посмотрите что выведется там где была навигация..
Сделал следующее:
garland_book_navigation() {
return "IT WORKS!";
}
опять вылезает ошибка :
Parse error: syntax error, unexpected '{' in Z:\home\new\www\themes\garland\template.php on line 38
с book.module ничего делать не надо. его можно только смотреть и все. Мы тут работаем только с template.php.
на 38 строке кода в указаном файле вы допустили ошибку.
Возьмите учебник по PHP и почитайте его, если же вам это не интересно - попросите какого нить друга програмиста помочь (которому вы доверите доступ к своему сайту) или наймите специалиста, который поможет вам за деньги.
Третий день пытаюсь сделать тоже самое для 6-ки... В конечном итоге уперся в один неразрешимый пока вопрос (использую CCK и contemplate) - как получить список дочерних страниц книги?
Добавлено:
Пересмотрел все таблицы. Где же хранится ссылка на родителя?
Мда. Друпал оказывается не так прост как была надежда.
В D6 структура book завязана на меню. См. в таблице book есть ссылка mlid, после см. таблицу menu_links WHERE module = 'book'. Там есть plid - родитель для mlid.
to Tankha:Третий день пытаюсь сделать тоже самое для 6-ки... В конечном итоге уперся в один неразрешимый пока вопрос (использую CCK и contemplate) - как получить список дочерних страниц книги?
Выложите результаты работы, в задних рядах тоже интересуются!!! : )
<подписка>
модуль Books это капитальный тупик - надо использовать таксономию.