WordPress как на ладони
Недорогой хостинг для сайтов на WordPress: wordpress.jino.ru

Функция для вывода последних комментариев

Начну с того, что комментарии в WordPress можно получить из базы данных с помощью функции get_comments(). Вот пример из описания функции:

# Получим последние комментарии списком

Этот код получает последние 10 комментариев в виде списка UL. Где текст комментария укорочен до 50 символов и является ссылкой на сам комментарий:

$args = array(
	'number'  => 10,
	'orderby' => 'comment_date',
	'order'   => 'DESC',
	'status'  => 'approve',
	'type'    => 'comment', // только комментарии, без пингов и т.д...
);

if( $comments = get_comments( $args ) ){
	echo '<ul>';
	foreach( $comments as $comment ){
		$comm_link = get_comment_link( $comment->comment_ID ); // может быть тяжелый запрос ...
		$comm_short_txt = mb_substr( strip_tags( $comment->comment_content ), 0, 50 ) .'...';

		echo '<li>'. $comment->comment_author .': <a rel="nofollow" href="'. $comm_link .'">'. $comm_short_txt .'</a></li>';
	}
	echo '</ul>';
}

/*
Данные в объекте $comment
stdClass Object
(
	[comment_ID] => 9727
	[comment_post_ID] => 477
	[comment_author] => Andrew
	[comment_author_email] => mail@gmail.com
	[comment_author_url] => 
	[comment_author_IP] => 178.45.177.200
	[comment_date] => 2015-22-01 00:27:04
	[comment_date_gmt] => 2015-22-28 21:27:04
	[comment_content] => текст коммента
	[comment_karma] => 0
	[comment_approved] => 1
	[comment_agent] => Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
	[comment_type] => 
	[comment_parent] => 9724
	[user_id] => 313
)
*/

Измените этот код под себя. Если по каким-то причинам такой вариант не подходит, то все что ниже как раз для вас.

Специальная функция для вывода последних комментариев

Чтобы вывести последние комментарии я пользуюсь своей функцией, которая расположена ниже. Её нужно поместить в файл functions.php вашей темы.

/**
 * Функция для вывода последних комментариев в WordPress. 
 * ver: 0.1
 */
function kama_recent_comments( $args = array() ){
	global $wpdb;

	$def = array(
		'limit'      => 10, // сколько комментов выводить.
		'ex'         => 45, // n символов. Обрезка текста комментария.
		'term'       => '', // id категорий/меток. Включить(5,12,35) или исключить(-5,-12,-35) категории. По дефолту - из всех категорий.
		'gravatar'   => '', // Размер иконки в px. Показывать иконку gravatar. '' - не показывать.
		'user'       => '', // id юзеров. Включить(5,12,35) или исключить(-5,-12,-35) комменты юзеров. По дефолту - все юзеры.
		'echo'       => 1,  // выводить на экран (1) или возвращать (0).
		'comm_type'  => '', // название типа комментария
		'meta_query' => '', // WP_Meta_Query
		'meta_key'   => '', // WP_Meta_Query
		'meta_value' => '', // WP_Meta_Query
		'url_patt'   => '', // оптимизация ссылки на коммент. Пр: '%s?comments#comment-%d' плейсхолдеры будут заменены на $post->guid и $comment->comment_ID
	);

	$args = wp_parse_args( $args, $def );
	extract( $args );

	$AND = '';

	// ЗАПИСИ
	if( $term ){
		$cats = explode(',', $term );
		$cats = array_map('intval', $cats );

		$CAT_IN = ( $cats[ key($cats) ] > 0 ); // из категорий или нет

		$cats = array_map('absint', $cats ); // уберем минусы
		$AND_term_id = 'AND term_id IN ('. implode(',', $cats) .')';

		$posts_sql = "SELECT object_id FROM $wpdb->term_relationships rel LEFT JOIN $wpdb->term_taxonomy tax ON (rel.term_taxonomy_id = tax.term_taxonomy_id) WHERE 1 $AND_term_id ";

		$AND .= ' AND comment_post_ID '. ($CAT_IN ? 'IN' : 'NOT IN') .' ('. $posts_sql .')';
	}

	// ЮЗЕРЫ
	if( $user ){
		$users = explode(',', $user );
		$users = array_map('intval', $users );

		$USER_IN = ( $users[ key($users) ] > 0 );

		$users = array_map('absint', $users );

		$AND .= ' AND user_id '. ($USER_IN ? 'IN' : 'NOT IN') .' ('. implode(',', $users) .')';
	}

	// WP_Meta_Query
	$META_JOIN = '';
	if( $meta_query || $meta_key || $meta_value ){
		$mq = new WP_Meta_Query( $args );
		$mq->parse_query_vars( $args );
		if( $mq->queries ){
			$mq_sql = $mq->get_sql('comment', $wpdb->comments, 'comment_ID' );
			$META_JOIN = $mq_sql['join'];
			$AND .= $mq_sql['where'];
		}
	}

	$sql = $wpdb->prepare("SELECT * FROM $wpdb->comments LEFT JOIN $wpdb->posts ON (ID = comment_post_ID ) $META_JOIN
	WHERE comment_approved = '1' AND comment_type = %s $AND ORDER BY comment_date_gmt DESC LIMIT %d", $comm_type, $limit );

	//die( $sql );  
	$results = $wpdb->get_results( $sql );

	if( ! $results ) return 'Комментариев нет.';

	// HTML
	$out = $grava = '';
	foreach ( $results as $comm ){
		if( $gravatar )
			$grava = get_avatar( $comm->comment_author_email, $gravatar );

		$comtext = strip_tags( $comm->comment_content );
		$com_url = $url_patt ? sprintf( $url_patt, $comm->guid, $comm->comment_ID ) : get_comment_link( $comm->comment_ID );

		$leight = (int) mb_strlen( $comtext );
		if( $leight > $ex )
			$comtext = mb_substr( $comtext, 0, $ex ) .' …';

		$out .= '
		<li>
			'. $grava .' <b>'. strip_tags( $comm->comment_author ) .':</b> 
			<a href="'. $com_url .'" title="к записи: '. esc_attr( $comm->post_title ) .'">'. $comtext .'</a>
		</li>';
	}

	if( $echo )
		return print $out;
	return $out;
}

Примеры использования

#1 Выводим последние комментарии

<ul>
	<?php kama_recent_comments("limit=10&ex=40"); ?>
</ul>

10 - это количество комментариев, которые будут показаны, а 40 - сколько символов из текста комментария будет выведено. Символы считаются после того, как из текста были вырезаны все HTML теги, чтобы сохранить равную длину текстов.

#2 Комментарии для постов из заданных рубрик/меток

Также в функции можно включать/исключать комменты к записям из указанных рубрик/меток/произвольных таксономий. ЗА это отвечает параметр term, указывать нужно id рубрик (увидеть их можно в админке в разделе "рубрики"). Для исключение перед id ставится "-":

<ul>
	<?php kama_recent_comments("limit=10&ex=40&term=5,10,34"); ?>
</ul>

Выведет 10 комментариев, с длинной текста до 40 символов, для постов из рубрик 5,10,34. Чтобы исключить эти рубрики нужно будет вызвать функцию так:

<ul>
	<?php kama_recent_comments("limit=10&ex=40&term=-5,-10,-34"); ?>
</ul>

Выведет 10 комментариев, с длинной текста до 40 символов, для всех постов, кроме постов из рубрик 5,10,34.

Одновременно включать и исключать рубрики нельзя! Впрочем, это лишено здравого смысла smile

#3 Возвращаем результат

Если нужно возвратить результат для дальнейшей обработки в php, а не выводить на экран, то параметр echo ставим в 0:

<?php kama_recent_comments('echo=0'); ?>

#4 Аватарки

Если нужно включить показ аватарок из сервиса gravatar, то указываем параметр gravatar как размер необходимой аватарки. Например, 20 - активирует показ аватарок и выведет аву шириной и высотой в 20px.

<ul>
	<?php kama_recent_comments('gravatar=20'); ?>
<ul>

1 6 2015
Полностью переписал функцию... Доп параметры и т.д.

9 ноября 2010
Добавил аватарки от сервиса gravatar.com в вывод функции.

13 июня 2010
Обновил код функции, до этого к тексту комментария добавлялось троеточие, даже если текст был короче чем выводимая длина. Теперь, если комментарий короче заданной длинны, то троеточие не добавляется.

21 августа 2010
По просьбе Анатолия v, добавил возможность выводить комментарии для постов из определенных рубрик (включать рубрики) или исключать комментарии к постам из определенных рубрик (исключать рубрики)

Функция для вывода последних комментариев из текущей категории

Эта старая функция, если работает то используйте, если не работает, то пользуйтесь функцией выше - kama_recent_comments().

/**
 * Функция для вывода последних комментариев из текущей категории.
 * 
 * Автор: Kama
 * ver: 0.1
 * 
 * Как работает:
 * в рубрике, выводит комменты из текущей и дочерних рубрик
 * в посте, выводит комменты из рубрик к которым принадлежит пост, работает если пост из нескольких рубриках
 * в постах дочерние рубрики рубрик поста не учитываются
 * Пример: echo kama_recent_comments_from_current_cat(10, 45, $gravatar='');
 */
function kama_recent_comments_from_current_cat( $limit=10, $ex=45, $gravatar=0 ){
	global $post, $cat, $wpdb;

	$limit = (int) $limit;
	$ex    = (int) $ex;

	// для дочерних рубрик
	if( $cat && $child_terms = get_categories( array('child_of' => $cat) ) )
		foreach( $child_terms as $term )
			$cat .= ','. $term->term_id;

	// для постов
	if( !$cat && is_singular() && $terms = get_the_category( $post->ID ) )
		foreach( $terms as $term )
			$cat .= $term->term_id . ',';

	$cat = rtrim($cat, ',');

	$JOIN = $AND = '';
	if( $cat ){
		$IN   = (strpos($cat,'-')===false) ? "IN ($cat)" : "NOT IN (". str_replace('-', '', $cat) .")";
		$JOIN = "LEFT JOIN $wpdb->term_relationships rel ON (p.ID = rel.object_id) LEFT JOIN $wpdb->term_taxonomy tax ON (rel.term_taxonomy_id = tax.term_taxonomy_id)";
		$AND  = "AND tax.taxonomy = 'category' AND tax.term_id $IN";
	}

	$sql = "SELECT * FROM $wpdb->comments com
	LEFT JOIN $wpdb->posts p ON (com.comment_post_ID = p.ID) $JOIN
	WHERE comment_approved = '1' AND comment_type = '' $AND
	ORDER BY comment_date_gmt DESC LIMIT $limit"; 

	$results = $wpdb->get_results( $sql );

	$out = $grava = '';
	foreach( $results as $comm ){
		if( $gravatar )
			$grava = get_avatar( $comm->comment_author_email, $gravatar );

		$comtext = strip_tags( $comm->comment_content );
		$leight = (int) mb_strlen( $comtext );
		if( $leight > $ex )
			$comtext = mb_strlen( $comtext, 0, $ex, 'UTF-8' ) .' …';

		$out .= '
		<li>
			'. $grava .'<b>'. strip_tags($comm->comment_author) .':</b> 
			<a href="'. get_comment_link($comm->comment_ID) .'" title="к записи: '. esc_attr($comm->post_title) .'">'. $comtext .'</a>
		</li>';
	}

	return $out;
}
192 коммента
Полезные 8 Вопросы 2 Все
  • Евгений smetskiy.com

    Все это хорошо, но почему нет примера, как это будет выглядеть ?

    Ответить24.Сен.2014 в 17:26 #
    • Kama7644

      Ну как-то не сделал скрин, поставьте код и посмотрите как будет выглядеть, от темы зависит в общем-то... pardon

      Ответить25.Сен.2014 в 01:52 #
  • Ярослав

    Добрый вечер, а можно как то с плагина ещё и рейтинг выводить коментариев

    Плагин комментариев Comment Ratings.

    1
    Ответить04.Ноя.2014 в 20:41 #
  • Денис

    Граватар малость не тавой, не выводится, а все остальное работает шикарно.

    Ответить28.Ноя.2014 в 08:35 #
  • CanaBeasT64 bezvreda.com

    Здравствуйте, Тимур! Пользуюсь вашей функцией вывода kama_recent_comments (как и многими другими). У меня такой вопрос: а вы тоже этой функцией вывода коментов пользуетесь? Почему спрашиваю - у меня данная функция выполняет 29 запросов к базе, может я что-то не так сделал. А у Вас данная страничка всего делает - SQL: 45 за 0,151 сек. Я себе тоже так хочу. wink
    Не понимаю, просмотрел еще раз функцию, написана идеально, и по идее делает вообще один составной запрос, но разница в get_num_queries до места вызова функции и после показывает именно 29 запросов... Что не так?

    Кстати, заметил ошибку у вас на сайте. В форме комментария если нажать на свой ник, там где написано "Здравствуйте, CanaBeasT !" Ссылка вместо профиля выдает 404 ошибку потому что ведет на страницу wp-kama.ru/wp-admin/profile.php а не на wp-kama.ru/profile

    Ответить16.Дек.2014 в 01:42 #
    • Нашел, get_comment_link($comment->comment_ID) в этом месте у меня делаются дополнительные запросы к бд. А Вы у себя нигде не сохраняли генерируемые ссылки, как у вас здесь, для пермалинков, например?
      Например в ячейку comment_author_url wink Видимо себе сделаю именно так, но еще подожду Вашего совета.
      Сгенерировал ссылки и добавил в вышеописанную ячейку, теперь беру оттуда wink
      Добавил хук, при добавлении комента, генерится ссылка и добавляется в базу.
      Подскажите более легкую замену wp_list_categories, а то делает слишком много запросов. А как Вы выводите рубрики? Спасибо.
      Странно, вчера wp_list_categories делала несколько запросов к БД, теперь на той же странице 1 запрос... Как так?))

      Ответить16.Дек.2014 в 16:52 #
      • Kama7644

        Такая оптимизация у меня настроена, но это только для записей... Не советую сохранять готовую ссылку, тем более в другую ячейку... Можно попробовать создать дополнительное поле. Но я все же не рекомендую. Учитывайте еще что запрос запросу рознь: эти дополнительные запросы очень легкие...

        Вообще я бы посоветовал не зацикливаться за запросах, учитывайте удобство. Если не нужны запросы, используйте объектный кэш.

        По умолчанию такое объектное кэширование в ВП не работает с диском, но для этого есть плагины. Например, в плагине страничного кэширования WP total cache.

        Ответить17.Дек.2014 в 14:41 #
        • Добрый день. Спасибо за ответ. Но я когда подключал плагины по кэшированию (в счастности Hyper Cache), у меня почему-то реклама тоже кэшировалась и похоже, что не только реклама... В общем в статистике ЯМетрики отображалось в разы меньше посетителей, а переходы по рекламе вообще не считались... Не понял в как и почему... Поэтому просто отключил плагин.

          Ответить17.Дек.2014 в 15:14 #
          • Kama7644

            Попробуйте другой плагин. В частности рекомендую познакомится с WP Total Cache. Там и страничное и объектное кэширование работает.

            1
            Ответить17.Дек.2014 в 23:13 #
    • Kama7644

      get_comment_link() создает дополнительные запросы. У меня ссылка через get_permalink() и ?all_comments выводится.

      Спасибо за багрепорт! thank_you

      Ответить17.Дек.2014 в 14:29 #
  • Алексей

    а как сделать вывод комментариев через эту функцию к каждой отдельной рубрике?
    я себе это так представляю:

    но не знаю как получить id текущей категории
    хотелось бы это в category.php добавить, чтобы для каждой категории были последние комментарии из неё

    Ответить29.Дек.2014 в 20:22 #
    • Вообще, на таких архивных страницах ID котегории находится в глобальной переменной $cat:

      $GLOBALS['cat']
      1
      Ответить30.Дек.2014 в 14:05 #
  • Здравствуйте!

    Почему-то если выводить дату комментария через human_time_diff() (пример есть у вас на сайте) то у всех комментариев получается одна и та же дата, да еще и на каждой странице она разная (где-то у комментариев пишется "45 лет назад", где-то "2 дня назад" хотя все они опубликованы в течении часа)

    В какую сторону копать? Дату подставлял и в обычном формате и в 'U' и в _gmt, ничего не помогает

    Ответить05.Фев.2015 в 15:29 #
    • Kama7644

      Функция human_time_diff() тут точно не при чем, она обрабатывает то что ей дают, сама ничего не делает. Если что-то не так, значит что-то не то ей даете...

      Каким кодом выводите? Такой:

      $time_diff = human_time_diff( get_comment_time('U'), current_time('timestamp') );

      Если такой, то копайте в сторону глобальной переменной $comment где-то она не так определяется...

      Ответить06.Фев.2015 в 01:41 #
      • Вообщем выяснил что "get_comment_time('U')" не работает.

        Использую верхний пример, но немного изменил вывод под себя, но вместо ".get_comment_time('U')." ничего не выводится, видимо не хватает какой-то информации, может надо к запросу в bd что-то добавить?

        Ответить06.Фев.2015 в 15:29 #
  • campusboy3431 www.youtube.com/c/wpplus

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

    [img]ссылка_на_картинку[/img][float=center]

    В комментариях при записях этот bb код обрабатывается. Как в твоем коде запустить такую обработку? Натолкни, пожалуйста. Вот что в коде плагина есть:

    add_filter ('comment_text', array('cImagePTS', 'replace_bb_cImage'));
    add_action('wp_print_styles', array('cImagePTS', 'load_style_cImage'));
    add_action('wp_print_scripts', array('cImagePTS', 'load_scripts_cImage'));
    add_action('comment_form', array('cImagePTS', 'upload_form_cImage'));
    Ответить23.Апр.2015 в 10:29 #
    • campusboy3431 www.youtube.com/c/wpplus

      Вопрос решен, в коде плагина нашёл:

      function replace_bb_cImage($img) {
      
      		$url = preg_replace('/.*\[img\](.*)\.jpg\[\/img\].*/ms', '$1', $img);
      		$url = parse_url($url);
      
      		$siteurl = get_option('siteurl');
      		$siteurl = preg_replace('/http:\/\/(.*)/', '$1', $siteurl);
      
      		if ($url['host'] == $siteurl) {
      			$img = preg_replace('/\[img\](.*)\.jpg\[\/img\]\[float=(left|right|center)\]/', '<a href="$1.jpg"> <img class="cimage_pts float$2" src="$1-small.jpg" alt="" /></a>', $img);
      		} else {
      			$img = preg_replace('/\[img\](.*)\.jpg\[\/img\]\[float=(left|right|center)\]/', '<a href="$1.jpg"> <img class="cimage_pts float$2" src="$1.jpg" alt="" /></a>', $img);
      		}
      
      		return $img;
      	}

      И применил её в твоём коде, Тимур. Спасибо!

      Ответить23.Апр.2015 в 10:47 #
    • campusboy3431 www.youtube.com/c/wpplus

      Вот же херня! Думаю, где-то был такой вопрос, посмотрел как у меня реализовано. Минут 15 потратил, чтобы найти этот комментарий. А он мой! Господи, он мой! И я же на него давно дал ответ.

      Ответить06.Сен.2015 в 15:28 #
  • @ Евгений

    Kama, на Вас последняя надежда smile

    Очень удобная функция вывода комментариев из текущий рубрики, как раз её и искал.

    Но очень нужно чтобы комментарии автора сайта не выводились (user_id автора =1).
    Как исключить собственные комментарии из вывода???

    $comments = get_comments('user_id>=2&status=approve&number=8');
    Ответить22.Май.2015 в 12:59 #
    • Kama7644

      Посмотрел я в код, кажется вам нужно использовать параметр author__not_in в функции get_comments().

      $comments = get_comments( array(
      	'author__not_in' => 1,
      	'status' => 'approve',
      	'number' => 8,
      ) );
      1
      Ответить22.Май.2015 в 15:59 #
  • Сергей

    Подскажите, а как добавить дивы к каждому значению(автор, текст) и как сделать чтобы в тексте абзацы заключались в тег p ?

    Ответить17.Июл.2015 в 13:10 #
    • Kama7644

      Для грамотной замены переносов на

      есть функция: wpautop(). Насчет дивов не понятно...

      Ответить18.Июл.2015 в 02:01 #
  • campusboy3431 www.youtube.com/c/wpplus

    Тимур, почему при запросе в базу данных не делал prepare, как сам рекомендуешь в статье про wpdb? Или в данном случае это не обязательно?

    Ответить06.Сен.2015 в 00:01 #
    • Kama7644

      Давно эту функцию писал, сейчас бы по другому сделал все. Очистка нужна наверное, $limit очистить например, если вдруг он в функцию динамически будет передаваться, то получиться дырка...

      Спасибо за замечание, сейчас поправлю. А в остальном, не вижу что-то где может быть это нужно.

      Ну и я prepare в кодах не часто использую. Он не всегда нужен вроде, только для строковых данных.

      Ответить06.Сен.2015 в 00:28 #
      • campusboy3431 www.youtube.com/c/wpplus

        Спасибо за быструю реакцию, я тогда подожду новый код smile И ещё. Пролистал комментарии в поисках советов, как исключить из этого списка комментарии людей с определенным ID, к примеру самого админа или же нежелательного комментатора. Но встретились лишь советы по get_comments, но тут-то своя методика "вытягивания" данных. Сможешь это дописать в своей функции или времени/желания нет?

        Ответить06.Сен.2015 в 00:33 #
        • Kama7644

          Переписал функцию полностью... Добавил юзеров и метазапросы Смотри kama_recent_comments(). Примеры тоже обновил, но там не все параметры описал...

          1
          Ответить06.Сен.2015 в 06:48 #
          • campusboy3431 www.youtube.com/c/wpplus

            Это же шик какой блеск! smile Функция, взорвавшая интернет! Правда, классная вещь, однозначно, пусть разрабы WP догоняютmosking Даже граватарки здесь работают (в прошлой версии не работали). Спасибо большое за труд. Кстати, где учил php и mysql: курсы, универ, самоучка? А то в "Обо мне" слишком мало сказано, хочется знать больше.

            -1
            Ответить06.Сен.2015 в 11:49 #
            • Kama7644

              Самоучка... Ну, разрабы конечно не отдыхают у них подход другой просто...

              1
              Ответить07.Сен.2015 в 10:35 #
          • campusboy3431 www.youtube.com/c/wpplus

            Кстати, как добавить hook в эту функцию, чтобы плагины, работающие с комментариями, могли так же участвовать в выводе комментариев? К примеру, плагины, которые преобразовывают bb коды в html. Ну и другие вещи smile

            Ответить06.Сен.2015 в 15:52 #
            • Kama7644

              Там же обрезается... Ну, вообще как-то так:

              // код...   
              	if( $leight > $ex )
              			$comtext = mb_substr( $comtext, 0, $ex ) .' …';
              
              	$comtext = apply_filters('comment_text', $comtext );
              Ответить07.Сен.2015 в 10:47 #
              • campusboy3431 www.youtube.com/c/wpplus

                Это в оригинале функции обрезается, я же у себя убрал обрезание, так как вывод натянул на вертикальный слайдер, потому ограничение там не нужно. Спасибо! Оказывается, всё элементарно с этими фильтрами, во всяком случае здесь.

                Ответить07.Сен.2015 в 10:49 #