Сниппет «прямого эфира» без использования Views и Organic Groups. Код нагло озаимствован из модуля Comment, модифицирован sql-запрос. Легко темизируется.
Использование:
а) скопировать код
б) создать новый блок, выбрав формат ввода «php-код», вставить код в блок, сохранить
в) вывести блок в нужном регионе
зы.следует добавить проверку - не гость ли оставил камент.
<?php
// Select the $number nodes (visible to the current user) with the most
// recent comments. This is efficient due to the index on
// last_comment_timestamp.
$number = 10;
$result = db_query_range(db_rewrite_sql("SELECT nc.nid
FROM {node_comment_statistics} nc
WHERE nc.comment_count > 0
ORDER BY nc.last_comment_timestamp DESC", 'nc'), 0, $number);
$nids = array();
while ($row = db_fetch_object($result)) {
$nids[] = $row->nid;
}
$comments = array();
if (!empty($nids)) {
// From among the comments on the nodes selected in the first query,
// find the $number most recent comments.
$result = db_query_range('SELECT c.nid, c.subject, c.cid, c.uid, c.timestamp, n.title, u.name
FROM ({comments} c
INNER JOIN {users} u ON c.uid = u.uid)
INNER JOIN {node} n ON n.nid = c.nid
WHERE c.nid IN ('. implode(',', $nids) .')
AND n.status = 1
AND c.status = %d
GROUP BY c.nid
ORDER BY c.cid DESC', COMMENT_PUBLISHED, 0, $number);
while ($comment = db_fetch_object($result)) {
$comments[] = $comment;
}
}
$items = array();
foreach ($comments as $comment) {
$items[] = '<b>'.l($comment->name, 'user/'. $comment->uid).'</b>' .' → '
. l($comment->title, 'node/'. $comment->nid, array('fragment' => 'comment-'. $comment->cid)) .'<br />';
}
if ($items) {
echo theme('item_list', $items);
}
?>
Обновление! Старый код выводил комментарии сплошным потоком, что приводило к ситуации, когда в списке комментариев выводились ссылки на все комментарии в одной и той же ноде. Это было абсолютно бесполезно, т.к. задача блока - показать все последние обновления в нодах, а не новые комментарии. Ведь нам достаточно знать, что в той или иной ноде появиились новые комментарии и все.
Для решения этой задачи в sql-запрос была добавлена конструкция "GROUP BY c.nid". Теперь эфир работает идеологически верно - показывает ссылки на последние 10 нод, где были новые комментарии, а не ссылки на 10 комментариев. Кроме того, я выделил имена пользователей жиром. Жирные они стали от хорошей жизни
О модификации попросил NightSlavyansk, демо на его сайте: http://www.nightslavyansk.ru
Обновление 2! Достопочтенный olk оптимизировал мой кривой код и предложил более легкий вариант, лишенный всяких недостатков.
Для 6.х:
<?php
$number=10;
$result = db_query_range(db_rewrite_sql(
"SELECT n.type,n.title,n.nid,cm.cid,u.uid,u.name,cm.cnt,cc.timestamp
FROM {node_comment_statistics} nc JOIN {node} n ON nc.comment_count > 0 AND n.nid=nc.nid
INNER JOIN (SELECT max(c.cid) as cid ,c.nid,count(c.cid) as cnt FROM {comments} c GROUP by c.nid ) cm
ON cm.nid=n.nid
INNER JOIN {comments} cc ON cc.cid=cm.cid
INNER JOIN {users} u ON u.uid=cc.uid
ORDER BY nc.last_comment_timestamp DESC"),0,$number);
$items=array();
while($comment=db_fetch_object($result)){
$items[] = '<strong>'.theme('username',user_load($comment->uid)).
':</strong> '. l($comment->title.' ('.$comment->cnt.')', 'node/'.
$comment->nid, array('fragment' => 'comment-'. $comment->cid));
}
if(count($items)){
print theme('item_list',$items);
}
?>
Для 5.х:
<?php
$number=10; // record count
$result = db_query_range(db_rewrite_sql(
"SELECT n.type,n.title,n.nid,cm.cid,u.uid,u.name,cm.cnt,cc.timestamp
FROM {node_comment_statistics} nc JOIN {node} n ON nc.comment_count > 0 AND n.nid=nc.nid
INNER JOIN (SELECT max(c.cid) as cid ,c.nid,count(c.cid) as cnt FROM {comments} c GROUP by c.nid ) cm
ON cm.nid=n.nid
INNER JOIN {comments} cc ON cc.cid=cm.cid
INNER JOIN {users} u ON u.uid=cc.uid
ORDER BY nc.last_comment_timestamp DESC"),0,$number);
$items=array();
while($comment=db_fetch_object($result)){
$items[] = '<strong>'.theme('username',$comment).
'</strong> → '. l($comment->title.' ('.$comment->cnt.')', 'node/'. $comment->nid, array('fragment' => 'comment-'. $comment->cid));
}
if(count($items)){
print theme('item_list',$items);
}
?>
Комментарии
Во во просил ребят поправить стиль для div.geshifilter > code ...
а так код нечитаемый
Убрал пока подсветку кода. Теперь читаемый?
Да Но все же надо-бы добавить в div.geshifilter > code { overflow: auto;} ...
Нет, как раз без подсветки не читаемый.
спасибо, полезно
ну скопируйте себе куда хотите и подсвечивайте привычно проблема, блин
Проверено в Drupal 5 - работает.
Багфикс: забыл выбрать из БД uid пользователя
а как сделать стрелочку а не знак "больше", между именем пользователя и текстом комментария?
Просто скопируйте код по-новой
черт, не думал что так просто
спасибо
немного соптимизировал ваш сниппет
Во первых, ваш не будет работать на PgSQL (так как более строгие требования к стандарту SQL, и требуется что бы в кляузе GROUP BY присутствовали все не агрегированные поля запроса), ну и во вторых все это можно сделать одним запросом
<?php
$number=10;
$result = db_query_range(db_rewrite_sql(
"SELECT n.type,n.title,n.nid,cm.cid,u.uid,u.name,cm.cnt,cc.timestamp
FROM {node_comment_statistics} nc JOIN {node} n ON nc.comment_count > 0 AND n.nid=nc.nid
INNER JOIN (SELECT max(c.cid) as cid ,c.nid,count(c.cid) as cnt FROM {comments} c GROUP by c.nid ) cm
ON cm.nid=n.nid
INNER JOIN {comments} cc ON cc.cid=cm.cid
INNER JOIN {users} u ON u.uid=cc.uid
ORDER BY nc.last_comment_timestamp DESC"),0,$number);
$items=array();
while($comment=db_fetch_object($result)){
$items[] = '<strong>'.theme('username',user_load($comment->uid)).
':</strong> '. l($comment->title.' ('.$comment->cnt.')', 'node/'.
$comment->nid, array('fragment' => 'comment-'. $comment->cid));
}
if(count($items)){
print theme('item_list',$items);
}
?>
Спасибо, Друг!
Ок, спасибо, поставлю
а этот, модифицированный код для 5-го подходит
а то у мну вообще ничего не выводит
Да вроде проверил на пятерке - работает. Главное что бы у вас хоть один комментарий был на любой вид материала
Проверено в Drupal 6.2 - работает.
Спасибо!
Странно, у меня наоборот на 5.10 работает, на 6.4 нет, ничего не отображает...
у меня даже веселлее
то показывает то что надо - жирных юзеров, то вообще ничего не показывает
В общем не понимаю
Под анонимусом некоторое время может не показывать (если у вас включено кэширование), под авторизованным пользователем вроде всегда должно нормально показывать
что то я запутался
Вставляю нижний код ничего не выводится
Вставляю верхний - выводятся и жирные пользователи тоже
И еще, комментарии выводятся не последние, а первые, то есть, кто первый оставил к теме каммент, тот и отображается. А все последующие нет.
Тут суть токова:
выводится имя пользователя оставившего последний комментарий и тайтл самого материала на который был комментарий (при этом ссылка идет имено на последний коммент).
Выводится 10 тайтлов материалов на которые были комменты в порядке от самого свежего коммента.
Почему не выводиться моим кодом, может мускул у вас старенький (я не помню с какой версии он поддерживает подзапросы в джойне - но начиная с пятой версии точно поддерживает), хотя если бы не поддерживал у вас выводилась бы была мускульная ошибка.
ни фига
ход выводит имя первого откомментировавшегося (первонаха) и ссылку на пост, причем ссылка на первый комментарий.
Мускул 5, могу показать php.ini
Да, у меня так работает верхний код - я его узнаю, потому что имя пользователя в b а не в стронгах
Кодеры!
Пожалуйста, следуйте друпаловским соглашениям по оформлению кода: http://drupal.org/coding-standards
Чем больше PHP в блоках, тем большее это зло
Не факт ! Любой подключенный модуль грузит систему гораздо больше (по крайней мере хук_init выполняется при любой загрузке страницы (это не говоря о том что модуль может потребовать подгрузки своих css и js)), кроме того удлиняется цепочка инвоке вызовов для переопределенных хуков), сниппет же в блоке вызывается только при условии что он "показывается" на данной странице и кроме того, в сниппете можно построить гораздо более оптимальный запрос (конечно в ущерб универсальности) ... так что я предпочитаю "простые" задачи решать через сниппеты.
Код в блоке:
<?php
include_once 'sites/all/extra/my_complicated_routines.inc';
do_my_complicated_routines();
?>
На мой взгляд, гораздо лучше, чем большие простыни.
И для написания блоков есть также hook_blocks.
Вообще то я поддерживаю whisk@drupal.org. Придерживайтесь стандартов, и не важно где будет размещен Ваш код, в блоке, в модуле или в теме.
Стандарты ведь придуманы не просто так, от балды.
А кто не хочет придерживаться стандартов пусть изобретает свой велосипед и пишет свой быдлокод.
Может еще в общественном туалете с посетителями соседних кабинок здороваться?
Я бы не стал сравнивать сообщество с туалетом.
Так с этим я и не спорил это просто еще один способ подключить сниппет, а где "простыня" будет находиться внутри блока или во внешнем файле (у меня кстати все сниппеты хранятся во внешних файлах) не так важно ...
Я и не сравнивал, не надо воспринимать на свой счет. Я гвоорю лишь о том, что интимная сторона жизни (читай: код блоков) должна находиться в состоянии, приятном для владельца, а не для стандартов написания кодов.
Ваша философия действует только в случае если Вы пишете свой собственный велосипед.
В сообществе написание кода это уже не интимное дело, а коллективное.
Сами подумайте, кто свою интимную сторону будет выкладывать в интернет на всеобщее обозрение?
А уж коли выложили, то придерживайтесь общепринятых норм общения (в данном случае общение кодом).
Вот такие пироги.
Я так и не понял, ГДЕ вы увидели "отступление" от норм кодирования принятых в друпал
Разгорелся такой горячий спор, из за проблемы которой в данном случае не существует
Знак "=" пробелами не отбит.
Ну и отступы то же....
Вы не воспринимайте это как личное оскорбление.
В любом случае, все очень благодарны за Ваш код.
У меня просто накипело. Сейчас работаю с программистом, который пишет так:
<?php
function frDBnewestFieldsAticle($arTables,&$number,$fields)
?>
один из множества примеров.
а почему у меня ошибку выдает такую:
user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DISTINCT(n.nid),cm.cid,u.uid,u.name,cm.cnt,cc.timestamp FROM node_comment_sta' at line 1 query: SELECT n.type,n.title, DISTINCT(n.nid),cm.cid,u.uid,u.name,cm.cnt,cc.timestamp FROM node_comment_statistics nc JOIN node n ON nc.comment_count > 0 AND n.nid=nc.nid INNER JOIN (SELECT max(c.cid) as cid ,c.nid,count(c.cid) as cnt FROM comments c GROUP by c.nid ) cm ON cm.nid=n.nid INNER JOIN comments cc ON cc.cid=cm.cid INNER JOIN users u ON u.uid=cc.uid ORDER BY nc.last_comment_timestamp DESC LIMIT 0, 10 in
что мне делать??
Версия друпал не та?
Поставила второй код, все нормально работает, спасибо.
Но, маленькая проблема - показывает комментарии только от гостей, без комментариев от зарегистрированных пользователей... А первый блок не выводит слово Гость вообще...
Что можно поправить во втором коде, чтобы и регистрированные и гости были целы ?
Вот адаптированный код для 5.х:
<?php
$number=10; // record count
$result = db_query_range(db_rewrite_sql(
"SELECT n.type,n.title,n.nid,cm.cid,u.uid,u.name,cm.cnt,cc.timestamp
FROM {node_comment_statistics} nc JOIN {node} n ON nc.comment_count > 0 AND n.nid=nc.nid
INNER JOIN (SELECT max(c.cid) as cid ,c.nid,count(c.cid) as cnt FROM {comments} c GROUP by c.nid ) cm
ON cm.nid=n.nid
INNER JOIN {comments} cc ON cc.cid=cm.cid
INNER JOIN {users} u ON u.uid=cc.uid
ORDER BY nc.last_comment_timestamp DESC"),0,$number);
$items=array();
while($comment=db_fetch_object($result)){
var_dump($comment); print '<br>';
$items[] = '<strong>'.theme('username',$comment).
':</strong> '. l($comment->title.' ('.$comment->cnt.')', 'node/'. $comment->nid, array('fragment' => 'comment-'. $comment->cid));
}
if(count($items)){
print theme('item_list',$items);
}
?>
Проблема была в различии входящих параметров у функции theme_username в 5.х и 6.х
Спасибо большое!
Все работает отлично!
Только, если использовать 2ой код перед блоком будет какой-то служебный код - как я понимаю список всех запросов к базе. Я убрала строчку
И все заработало как надо
Спасибо!!!
а как сюда аватару завернуть в imagecache?
Для 5-ки работает только самый первый, неоптимизированный код.
Все остальные ничего не выдают. Пусто. Ни ошибок, ничего.
PHP - 5.2.6
База данных MySQL - 4.1.22
Drupal - 5.9
Watchdog выдает такую хрень на последний код:
Внимание! Вопрос: Откуда берется DISTINCT, если у меня его нет в коде?
Его добавляет db_rewrite_sql(...), попробуйте убрать
Спасиба! Заработало
Вот конечный код для 5-ки, может кто-то такие же проблемы испытывал:
$number=10; // record count
$result = db_query_range(
"SELECT n.type,n.title,n.nid,cm.cid,u.uid,u.name,cm.cnt,cc.timestamp
FROM node_comment_statistics nc JOIN node n ON nc.comment_count > 0 AND n.nid=nc.nid
INNER JOIN (SELECT max(c.cid) as cid ,c.nid,count(c.cid) as cnt FROM comments c GROUP by c.nid ) cm
ON cm.nid=n.nid
INNER JOIN comments cc ON cc.cid=cm.cid
INNER JOIN users u ON u.uid=cc.uid
ORDER BY nc.last_comment_timestamp DESC",0,$number);
$items=array();
while($comment=db_fetch_object($result)){
$items[] = '<strong>'.theme('username',$comment).
'</strong> → '. l($comment->title.' ('.$comment->cnt.')', 'node/'. $comment->nid, array('fragment' => 'comment-'. $comment->cid));
}
if(count($items)){
print theme('item_list',$items);
}
?>
Попутно вопрос еще по усовершенствованию.
Как модифицировать код, чтобы он выдавал количество непрочтенных камментов рядом с общим количеством камментов?
К примеру:
Вася Пупкин: Как модифицировать блог? (2/74)
И вдогонку: Как вынести счетчик количества ЗА пределы ссылки на ноду как в примере строкой выше?
И вот еще вопрос.
Строка кода:
делает вот такой вот вывод:
<a href="/testurl" fragment="comment-6471">
С синтаксисом html я знаком не по наслышке, но что такое fragment для тега
<a>
хоть убей не знаю. Вероятно код обрабатывается не корректно. Как это безобразие поправить, чтобы выводился нормальный формат:<a href="/testurl#comment-6471">
в 5-ке формат функции l(...) несколько другой
l($text, $path, $attributes = array(), $query = NULL, $fragment = NULL, $absolute = FALSE, $html = FALSE)
соответственно ваш код должен выглядеть несколько по другому а именно
' → '. l($comment->title.' ('.$comment->cnt.')', 'node/'. $comment->nid, NULL,'comment-'. $comment->cid);
что бы вынести счетчик за ссылку то достаточно его вынести из ф-ции l()
' → '. l($comment->title, 'node/'. $comment->nid, NULL,'comment-'. $comment->cid).' ('.$comment->cnt.')';
Пасиба! Только ты коечто забыл, вот правильный код:
Замечательный снипет. Есть один недостаток, нет выборки комментариев по типу материала или категории или словаря. В моем случае мне необходима была выборка комментариев только из блогов. Я добавил в ваш снипет строчку WHERE n.type='blog'
Подскажите, я не разобрался как сделать выборку комментариев из определенного термина? Как должен выглядеть sql запрос, в данном примере:
$number=10;
$result = db_query_range(
"SELECT n.type,n.title,n.nid,cm.cid,u.uid,u.name,cm.cnt,cc.timestamp
FROM {node_comment_statistics} nc JOIN {node} n ON nc.comment_count > 0 AND n.nid=nc.nid
INNER JOIN (SELECT max(c.cid) as cid ,c.nid,count(c.cid) as cnt FROM {comments} c GROUP by c.nid ) cm
ON cm.nid=n.nid
INNER JOIN {comments} cc ON cc.cid=cm.cid
INNER JOIN {users} u ON u.uid=cc.uid
WHERE n.type='blog'
ORDER BY nc.last_comment_timestamp DESC",0,$number);
$items=array();
while($comment=db_fetch_object($result)){
$items[] = '<strong>'.theme('username',user_load($comment->uid)).
'</strong> → '. l($comment->title.' ('.$comment->cnt.')', 'node/'.
$comment->nid, array('fragment' => 'comment-'. $comment->cid));
}
if(count($items)){
print theme('item_list',$items);
}
?>
Сам же себе даю ответ
<?php
$number=10;
$result = db_query_range(
"SELECT n.type,n.title,n.nid,cm.cid,u.uid,u.name,cm.cnt,cc.timestamp
FROM {node_comment_statistics} nc JOIN {node} n ON nc.comment_count > 0 AND n.nid=nc.nid
INNER JOIN (SELECT max(c.cid) as cid ,c.nid,count(c.cid) as cnt FROM {comments} c GROUP by c.nid ) cm
ON cm.nid=n.nid
INNER JOIN {comments} cc ON cc.cid=cm.cid
INNER JOIN {users} u ON u.uid=cc.uid
JOIN {term_node} tn ON n.nid=tn.nid
WHERE n.type='blog' AND tn.tid=85
ORDER BY nc.last_comment_timestamp DESC",0,$number);
$items=array();
while($comment=db_fetch_object($result)){
$items[] = ''.theme('username',user_load($comment->uid)).
' → '. l($comment->title.' ('.$comment->cnt.')', 'node/'.
$comment->nid, array('fragment' => 'comment-'. $comment->cid));
}
if(count($items)){
print theme('item_list',$items);
}
?>
А как сделать чтобы вместо "Гость" отображалось имя анонима, которое он ввёл при публикации коммента?
У гостей имен нет. Соответственно, не нужно давать им возможность подписываться кем попало. Такая у меня позиция.
почему то получаю ошибки в логах при использовании версии для 6-ки
Обратите внимание вот на этот участок запроса в ошибке WHERE (n.type <> 'webform_report')
видимо db_rewrite_sql не правильно реврайтит запрос.
Попробуйте просто убрать db_rewrite_sql
да, спасибо
что интересно , указывает модуль webform_report
возможно как то с ним связано
Может кто знает, как сюда добавить название группы из Organic groups.
Что бы на выходе было
имя→название группы→заголовок статьи
Ну и если знаете, то еще интерессует фильтрации закрытая-открытая группа, ну и если из определенных групп.
Я присоединяюсь к вопросу. Как вывести сюда имя группы? Заранее спасибо.
Смотрите Shvabr.ru
швабр для пятой
встречный вопрос, а если сделать во вьюсе. и скопировать от туда код-снипет - будет работать?
Я сделал вьюсами. Пусть пока так и остается, только темизировать осталось чутка. Пусть так и остается, вьюсы для прототипирования идеальны
Модуль PM_Lite гробит сниппет, т.к. некорректно переписывает запрос к БД (пытается найти поле type в таблице comments, где его нет). Будьте в курсе
если делать такой блок вьюсами, то сильно отличается загрузка в сравнении с реализацией снипетом?