Сниппет для вывода анонсов нод определенного типа (с пейджером и без)

Данное решение позволяет воплотить вывод в блоке заданного количества публикаций только определенного типа(или типов). Если число публикаций больше заданного на вывод, то для отображения остальных задействован(как вариант) стандартный друпаловский механизм пейджинга (разбиения на «подстраницы»).

Применение сего сниппета может быть весьма широким. Например, при формировании контента для основной страницы сайта. Согласитесь, что первая страничка с анонсами последних публикаций, поделенная на тематические блоки, гораздо более «юзабильна» и информативна для потенциальных прихожан ресурса, чем «дефолтовый» скучный список тизеров Drupal`а.

На многих сайтах данное решение позволит отказать полностью от услуг замечательного, но весьма объемного и жадного до ресурсов сервера модуля Views.

Список определенного настройками количества тизеров нод нужных нам типов:

<?php

/* «Набиваем» в массив типы нод, тизеры которых желаем выводить. */
$types     = array('ТИП_РАЗ', 'ТИП_ДВА', 'ТИП_...');

/* Указываем лимит(количество) публикаций для отображения. */
$num_nodes = 5;

/* Формируем запрос к базе для получения необходимых данных(в данном случае nid ноды). */
$sql       = "  
SELECT n.nid
FROM {node} n
WHERE n.status = 1
AND n.type IN ("
. db_placeholders($types, 'text') .")
ORDER BY n.created DESC
"
;

/* Ограничиваем количество возвращаемых из БД значений с помощью функции db_query_range(), подставляя ей аргументом значение переменной $num_nodes. */
$result = db_query_range(db_rewrite_sql($sql), $types, 0, $num_nodes);

/* И в завершении «приходимся» циклом по отобранным данным, выводя на экран конечный результат - тизеры/анонсы нод - с помощью функции node_view(). */
while ($n = db_fetch_object($result)) {
print node_view(node_load($n->nid), 1, 0);
}

?>

Для добавления к списку тизеров «постраничной навигации», дабы посетитель мог с текущей же страницы увидеть все доступные ему анонсы, немного видоизменяем код:

<?php

/* «Набиваем» в массив типы нод, тизеры которых желаем выводить. */
$types     = array('ТИП_РАЗ', 'ТИП_ДВА', 'ТИП_...');

/* Указываем лимит(количество) публикаций для отображения. */
$num_nodes = 5;

/* Формируем запрос к базе для получения необходимых данных(в данном случае nid ноды). */
$sql       = "  
SELECT n.nid
FROM {node} n
WHERE n.status = 1
AND n.type IN ("
. db_placeholders($types, 'text') .")
ORDER BY n.created DESC
"
;

/* Для ограничения количества возвращаемых из БД значений теперь используем функцию pager_query() (а не db_query_range(), как в предыдущем примере). */
$result = pager_query(db_rewrite_sql($sql), $num_nodes, 0, NULL, $types);

/* И в завершении «приходимся» уже знакомым нам циклом по отобранным данным, выводя на экран конечный результат - тизеры/анонсы нод - с помощью функции node_view(). */
while ($n = db_fetch_object($result)) {
print node_view(node_load($n->nid), 1, 0);
}

/* Добавляем в низ списка тизеров «постраничную навигацию»(пейджер). */
print theme('pager', NULL, $num_nodes);

?>

Альтернативный, «расширенный» вариант сниппета.

Ниже размещен пример кода с «самостоятельным» формированием содержания тизеров. Без помощи функции node_view().

Наш тестовый тизер будет состоять из заголовка, даты создания, и вводного текста:

<?php

$types     = array('ТИП_РАЗ', 'ТИП_ДВА', 'ТИП_...');
$num_nodes = 5;

$sql = "SELECT n.nid, n.title, n.created, nr.teaser
 FROM {node} n
 LEFT JOIN {node_revisions} nr ON n.vid = nr.vid
 WHERE n.status = 1
 AND n.type in ("
. db_placeholders($types, 'text') .")
 ORDER BY n.created DESC"
;
 
 $result = db_query_range($sql, $types, 0, $num_nodes);
 
 while ($n = db_fetch_object($result)) {
    $output  = '<div class="node">';
    $output .= '<h2 class="title">' . l($n->title, 'node/' . $n->nid). '</h2>' ;
    $output .= '<div class="submitted">' . format_date($n->created, 'medium') . '</div>';
   
    /* Что бы все было аккуратно, ровно, и текст тизера был действительно похож на текст анонса, удалим из него ненужные пока теги функцией strip_tags(), и «подровняем» текст до еще более точно заданного количества символов в нем функцией truncate_utf8()(в коде примера - до 200 символов).
               
                Тут, конечно, было бы уместнее использовать текст ноды целиком, но мы «запросили» у базы именно тизер, посему используем его(для наглядности описываемых действий достаточно). Если дополнительная обработка текста не нужно, то ниже закомментирован код вывода текста тизера «как он есть», раскомментируйте его и закомментируйте текущий.  */

    $output .= '<div class="content">' . truncate_utf8(strip_tags($n->teaser), 200, TRUE, TRUE) . '</div>';
    //$output .= '<div class="content">' . $n->teaser . '</div>';
   
    $output .= '</div>';
    print $output;
  };

?>

Добавление к списку пейджера происходит путем модификации кода по аналогии с вариантом, где тизер вызывается функцией node_view().

Dalay
Комментирование закрыто

Комментарии

Благодарю, всё хорошо работает, кроме пейджера - он считается и показывает листинг от общего количества материалов, а не тех которые мы отобрали запросом к БД. Если вам не трудно, исправьте пожалуйста, а то я ещё совсем новичок в друпале!

Так нечего исправлять, все правильно написано.

Сам по себе вызов пейджера ничего вам не отобразит. Для этого в коде и используется, в самом начале, запрос через функцию pager_query(). Дальнейшее $output .= theme('pager', NULL, 5); работает лишь с результатом запроса.

Может быть вы код запихали не туда, и пейджер перехватывает результат другого запроса. Вышеописанный код предназначен для вставки в блок. Если хотите использовать в файлах темы, то его надо обернуть в новую функцию, и вызывать уже ее.

Кажется разобрался :)
Вот только хотелось бы вместо циферки 5 вставить переменную в которой содержится число "по-умолчанию" для количества выводимых материалов. Ещё раз большое человеческое спасибо! :)

:) Так подставьте переменную, что мешает?

Автору большое спасибо за нужную инфу, благодаря Вам проблема с нестандартным выводом похожих материалов решена! Успехов Вам и Вашему сайту! ;)

Здорово, но было бы еще здровее, если бы была возможность вывести анонсы не всех материалов из определеного типа материалов, а из определенного словаря. Короче, скрестить данное с этим: drupalka.ru/node/42

Так посмотрите оба кода и дополните недостающим из одного другой.

то есть выбрать по типу терминов из определенного словаря. Например, словарь "Рубрики", в нем есть термины "О нашем отдыхе", "О нашей работе", .. "Наш спорт". Нужно вывести анонсы статей из заданных рубрик. Анонс - ссылка на саму статью.

Спасибо! Хороший у Вас сайт :) Единственно, если бы Вы в конце поста приводили ещё скриншот результата, вообще супер бы было :))

Т.е., представить без скрина, как выглядит список анонсов с пейджером внизу реально тяжело? )

Чего то не работает. Я правильно понял, можно скопировать код без изменений вставить в блок и в блоке будут выводится анонсы story и page. Формат ввода ставлю php. В чём может быть проблема?

К уже написанному больше добавить нечего.

Спасибо за статью! У меня получилось выводить тизеры новостей на главной странице под вступительной статьей, но даты у тизеров почему-то отображаются не свои, а дата создания статьи на главной странице.
Не подскажете, как поправить? У меня Друпал 6 и тип документов n.type = 'news'(а статья на главной - тип 'page')

Очень смутно осознал проблему, что бы что-то подсказать. Согласно коду дата у тизеров должна отображаться в та же(и в том же формате), что и при «стандартном» выводе списка анонсов (функция node_view()).

Вот, посмотрите мой сайт: smt точка eu5 точка org
В новостной ленте все даты новостей разные, а на главной в блоке - дата у всех новостей одна - дата создания статьи на главной странице.

Вверху блока вывела print_r($node);
При выведении отедельно дат node_load($node->nid)->created - даты выводятся правильно (разные), а при обработке node_view всё портится и вставляется дата статьи page.

Попробуйте в коде сниппета изменить имя переменной $node на другое (например $xnode), все вхождения. Видимо «подхватывается» «основной» обьект $node страницы.

Исправила на $xnode, но ничего не изменилось :(

А можно как-то обойтись без node_view? Как-нибудь по-другому сделать вывод тизеров?

Конечно же можно. Попозжа накидаю альтернативу.

Спасибо, буду ждать :)

Коды пофиксил и дополнил.

Спасибо большое! Всё заработало :)) Я только немного стилей своих добавила.

С пасибо за пост, помог.
Но столкнулся с интересной проблемой.
При выполнении одного запроса(закоменченый) пейджер рисуется и всё нормально, а вот при выполнении второго запроса выводится количество записей, указанное в $limit, а
пейджера нет, хотя запрос возвращает необходимое количество строк, большее чем $limit

 $limit = 3;
/*
$types     = " 'story', 'page' ,'image','message' ";
$sql = "SELECT n.nid, n.created, n.title, n.type,nr.teaser
 FROM {node} n
 LEFT JOIN {node_revisions} nr ON n.vid = nr.vid
 WHERE n.status = 1
 AND n.type in (". $types .")
 ORDER BY n.created DESC";
*/


$sql ="SELECT n.nid, n.created, n.title, n.type, nr.teaser, min(kart.field_addedimage_fid), f.filepath
FROM node n, node_revisions nr,
content_field_addedimage kart left JOIN files f ON   f.fid = kart.field_addedimage_fid
WHERE n.status =1
AND n.vid = nr.vid
AND kart.nid = n.nid
GROUP BY n.nid  ORDER BY n.created DESC"
;

$result = pager_query($sql, $limit);
/*
вывод тизеров
*/

print theme('pager', null, $limit);

Проблему кажется нашел.
Запрос
SELECT count(*)
FROM node n, node_revisions nr,
content_field_addedimage kart left JOIN files f ON f.fid = kart.field_addedimage_fid
WHERE n.status =1
AND n.vid = nr.vid
AND kart.nid = n.nid
group by n.nid ORDER BY n.created DESC

возвращает не резульирующее количество строк, а кучу строк с числом 2

очень полезный сниппет)спасибо)
а не подскажите как сделать,чтобы выводились анонсы нод определенного типа по дате, которая указанна в содержимом текста? то есть выводились материалы, в которых дата в содержимом больше или равна текущей дате.
я не очень понимаю как в таком случае должен выглядеть sql-запрос:)

Спасибо за сниппет. Подскажите, пожалуйста, еще 2 нюанса.

1. Как ограничить общее количество выводимых материалов с использованием пейджера (надо 2 в блоке и всего 10).
2. Как в данный сниппет подвязать пейджер без перезагрузки страницы.