WordPress как на ладони
wordpress jino

Функция для вывода последних записей в WordPress

Замена виджету WordPress для вывода последних записей или замена сложного кода для выборки последних записей.

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

Я к виджетам отношусь очень негативно - они ограничены, поэтому, по возможности вообще не использую виджеты, даже когда делаю что-нибудь на заказ.

На основе вышеизложенного предлагаю вашему вниманию, еще одну функцию - Вывод последних записей в WordPress. С её помощью можно более гибко настроить вывод, если вы хоть немного разбираетесь в хтмл и css. Так же, можно использовать эту функцию в любых местах шаблона. Например, предположим, нам нужно вывести список последних записей из какой-либо категории на главной странице или наоборот, вывести список последних записей из всех категорий, кроме некоторых.

Для этих целей эта функция подойдет как-нельзя лучше, потому что обычно, для этого используется функция WordPress get_posts(), или вывод оформляется через query_posts(), с последующим оформлением формата вывода, через foreach. Для новичков это не всегда удобно.

Использование функции - последние записи в WordPress

Вставляем нижеследующую функцию в файл темы functions.php или в файл где, мы будем выводить последние записи (например, sidebar.php)

/**
 * Выводит на экрна список последних записей.
 * 
 * @param  integer [$post_num = 5]   Количество ссылок
 * @param  string [$format = '']     {avatar} {author}: {date:j.M.Y} - {a}{title}{/a} ({comments})
 * @param  string [$cat = '']        Категории из которых нужно выводить (5,15) или которые нужно исключить (-5,-15), 
 *                                   через запятую (одновременно включение и исключение не работает (не имеет смысла) )
 * @param  string [$list_tag = 'li'] Тег списка
 * @param  boolean [$echo = true]    Выводить на экран или возвращать
 *                                                          
 * @return string  HTML.
 *                v 0.1
 */
function kama_recent_posts( $post_num = 5, $format = '', $cat = '', $list_tag = 'li', $echo = true ){
	global $post, $wpdb;

	$cur_postID = $post->ID;

	// исключим посты главного запроса (wp_query)
	foreach( $GLOBALS['wp_query']->posts as $post ) $IDs .= $post->ID .',';
	$AND_NOT_IN = ' AND p.ID NOT IN ('. rtrim($IDs, ',') .')';

	$DISTINCT = '';

	if( $cat ){
		$JOIN = "LEFT JOIN $wpdb->term_relationships rel ON ( p.ID = rel.object_id )
			LEFT JOIN $wpdb->term_taxonomy tax ON ( tax.term_taxonomy_id = rel.term_taxonomy_id  ) ";
		$DISTINCT = "DISTINCT";
		$AND_taxonomy = "AND tax.taxonomy = 'category'";
		$AND_category = "AND tax.term_id IN ($cat)";

		// Проверка на исключение категорий
		if( strpos($cat, '-')!==false )
			$AND_category = 'AND tax.term_id NOT IN ('. str_replace( '-','', $cat ) .')';

	}
	// если нужно показать автора
	if( false !== strpos($format, '{author}') ){
		$JOIN .= " LEFT JOIN $wpdb->users u ON ( p.post_author = u.ID )";
		$SEL = ", u.user_nicename AS author, u.user_email, u.user_url";

		// если нужно показать аватар (gavatar)
		if( strpos($format, '{avatar}')!==false )
			$av = "<img src='http://www.gravatar.com/avatar/%1\$s?s=25' alt='' />";
	}

	$sql = "SELECT $DISTINCT p.ID, post_title, post_date, comment_count, guid $SEL
	FROM $wpdb->posts p $JOIN
	WHERE post_type = 'post' AND post_status = 'publish' $AND_category $AND_taxonomy $AND_NOT_IN 
	ORDER BY post_date DESC LIMIT $post_num";
	$results = $wpdb->get_results($sql);

	if( ! $results )
		return false;

	preg_match('~\{date:(.*?)\}~', $format, $date_m );
	foreach( $results as $pst ){
		$x == 'li1' ? $x = 'li2' : $x = 'li1';
		if ( $pst->ID == $cur_postID ) $x .= " current-item";

		$a = '<a href="'. get_permalink($pst->ID) .'" title="'. esc_attr($pst->post_title) .'">';

		if( $format ){
			$avatar = $av ? sprintf( $av, md5($pst->user_email) ) : '';
			$date = apply_filters('the_time', mysql2date($date_m[1], $pst->post_date));
			$Sformat = str_replace( $date_m[0], $date, $format);
			$Sformat = str_replace(
				array('{title}',                   '{a}', '{/a}', '{author}',             '{comments}',         '{avatar}'),
				array( esc_html($pst->post_title), $a,    '</a>', esc_html($pst->author), $pst->comment_count,  $avatar   ),
				$Sformat
			);
		}
		else
			$Sformat = $a . esc_html($pst->post_title) .'</a>';

		$out .= "\n<$list_tag class='$x'>{$Sformat}</$list_tag>";
	}

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

Там, где нужно вывести последние записи, вызываем функцию используя, следующий код:

<ul>
	<?php kama_recent_posts (5); ?>
</ul>

// где, 5 это количество выводимых записей.

Дополнительные возможности функции

  1. Можно настроить формат вывода (формат передается во втором параметре $format = '');
  2. Можно, исключить или наоборот, включить какие-либо категории;
  3. Можно изменить тег списка (вместо li списка использовать, например, div).
Для настройки формата вывода используйте:
  • {comments} - покажет колличество комментариев у статьи;
  • {title} - заголовок статьи;
  • {date:j.M.Y} - дата в формате j.M.Y (11.Апр.2010);
  • {a} и {/a} - тег ссылки. Открывается и закрывается.

Вызов будет таким:

<ul>
	  <?php kama_recent_posts (5, '{a}{title}{/a} ? {date:j.M.Y} // {comments}');  ?>
</ul>
// выведет список в формате - <li class='li1'><a href='http://ссылка' title='Заголовок статьи'>Заголовок статьи</a> ? дата // количество комментариев</li>
Пример исключения или включения каких-либо категорий:

Для исключения категорий в третьем параметре передаем ID категорий через запятую, со знаком "минус" (пример: -5,-15,-20)

Для вывода записей только из указанных категорий (включения категорий) передаем в третьем параметре ID категорий через запятую (пример: 5,15,20)

<ul>
	  <?php kama_recent_posts (5, '', '5,15,20');  ?>
</ul>
// выведет список последних записей только из категорий, ID которых равны 5, 15 или 20

<ul>
	  <?php kama_recent_posts (5, '', '-5,-15,-20');  ?>
</ul>
// выведет список последний записей из всех категорий, кроме 5, 15 или 20

Так же, как и обычно в функциях WordPress, к тегу li добавляется сласс current-item (<li class='li1 current-item'></li>), если ID просматриваемой записи равен ID записи из списка, т.е. если мы просматривает одну из записей, находящихся в списке. Используя этот класс, можно визуально выделить запись в списке, через css.

Функция для вывода последних записей в WordPress 157 комментариев
Полезные 2 Вопросы 2 Все
  • Андрей cайт: bdseo.ru @

    Привет, подскажи, как ты выводишь код в блоге у себя?
    каким плагином? smile
    именно код в тексте, примеры разные smile
    спс

    Ответить1.7 года назад #
    • Kama4485

      Это не плагин - это мой код. Там все сложно с введением маркдауна все совсем сложно... Задавай конкретные вопросы подскажу...

      Коротко так:

      Подсветка с помощью hightlightjs

      Код вставляется в тройные ` которые затем превращаются в PRE тег и внутри все спец символы HTML заменяются на сущности.

      Ответить1.7 года назад #
      • Андрей cайт: bdseo.ru @

        спс, в целом я сам могу написать функции и теги, но думал что уже есть готовый плагин smile

        Ответить1.7 года назад #
  • Вадим

    Привет, Тимур. Подскажи, пожалуйста, какой можно использовать код для вывода 5 последних записей на блоге (участвуют все категории), кроме уже открытой статьи, чтобы не было ссылки самой на себя.

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

    1
    Ответить1.6 года назад #
    • Ростислав

      Тоже интересует вопрос

      Ответить1.4 года назад #
    • Kama4485

      Для вывода последних записей проще использовать get_posts(), чтобы исключить тек. запись, укажите её ID в параметре exclude.

      Пример вывода 10 послед. записей, с исключением текущей:

      <?php
      global $post;
      $lastposts = get_posts( array('posts_per_page'=>10, 'exclude'=>$post->ID );
      foreach( $lastposts as $post ){
      	setup_postdata($post);
      	?>
      	<div>
      		<?php the_date(); ?>
      		<br />
      		<?php the_title(); ?>
      		<?php the_excerpt(); ?>
      	</div>
      	<?php
      }
      wp_reset_postdata();
      Ответить1.4 года назад #
  • campusboy1832 cайт: wp-plus.ru

    Прелесть get_post, что она кеширует результаты, а в этой функции кеширование я не вижу. Может стоит добавить? Или я глупость сморозил? smile Тимур, поправь меня пожалуйста, если не прав.

    Ответить1.5 года назад #
    • Kama4485

      get_post() не кэширует запрос, а кэширует данные записей, причем только для текущей генерации, если только не установлен плагин постоянного объектного кэширования, которого в 99% нет... В общем по большому счету ничего не кэишруется...

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

      Сейчас запустил проверки (вывод полностью одинаковый) - это факты:

      kama_recent_posts() - 1/500 повторений - 0.00382 сек./0.39681 сек.

      get_posts() - 1/500 повторений - 0.00799 сек./0.87335 сек.

      Т.е. get_posts в 2 раза проигрывает. Это без объектного кэширования, с ним, я думаю, get_posts() выиграет. Но если добавить его в эту функцию, там 3 строчки всего, тогда она выиграет во много раз...

      Вообще все это конечно мелочи, тут больше нужно на удобство программирования ориентироваться, и если нужен какой-то отличный вывод от того что предлагает эта функция, то наверное правильнее использовать get_posts()...

      Ответить1.5 года назад #
  • campusboy1832 cайт: wp-plus.ru

    Отвлеченной сообщение. Тимур, может попробовать микроразметку, чтоб поиск лишняка не хватал? Или html5 атрибуты.

    Ответитьгод назад #
    • Kama4485

      Спасибо, руки не доходят этим заняться...

      Ответитьгод назад #
  • Димонтий

    Блин, чувак, это просто невероятно! Только у меня возникает какой-то нестандартный вопрос по водрпрессу, как ты его уже решил! Всегда нахожу у тебя на сайте готовые решения! Спасибище тебе огромное!

    1
  • C. cайт: dad.ru

    Почему-то у меня выводит только список тех последних записей, к которым есть комментарии. Если у записи нету комментариев, то она почему-то не выводится. Это так и должно быть? Я думал будут выводиться все записи без условия наличия комментариев к ней.

    • C. cайт: dad.ru

      Разобрался. Всё нормально работает, это просто у меня исключился из списка пост как раз без комментариев, на странице которого я тестировал виджет.

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

      • C. cайт: dad.ru

        Спасибо. Уже и с этим разобрался. Удалил часть кода. Сам с собой поговорил smile

        В любом случае автору Огромное Спасибо и Респект. thank_you

  • Андрей

    Приветствую, гуру кодинга smile

    <?php $the_query = new WP_Query('orderby=rand&showposts=5'); ?>
    <ul><?php while  ($the_query->have_posts() ) : $the_query->the_post(); ?>
    
    	 <li>
    		 <a title="<?php the_title(); ?>" href="<?php the_permalink() ?>"><?php the_post_thumbnail(); ?></a> 
    	<a title="<?php the_title(); ?>" href="<?php the_permalink(); ?>"><?php the_title(); ?></a> </li>
    
    <?php endwhile; ?></ul>   
    <?php wp_reset_postdata();?>

    Имеется код вывода списка статей, который размещён в сайдбаре. Мне хотелось бы выделять отдельным классом (стилем) открытую в данный момент статью (при условии, что она есть в списке, а то вдруг 30 статей будет, а по списку она будет 21, а выводится всего 20) в этом общем списке, для лучшей навигации.
    Как это реализовать в этом коде?

  • Михаил cайт: trapeznaya.ucoz.ru

    Здравствуйте Kama. А подскажите как сделать список например 5 последних редакций, как у вас в сайдбаре, т.е. не последние записи выводить, а последние которые редактировались. Спасибо!

    • Kama4485

      У меня это такой код:

      // Последние отредактированные записи
      $editted_list = [];
      // Создадим новую функцию которая добавит условие where в запрос
      function __temp_filter_where( $where = '' ){
      	$where .= " AND post_date != post_modified ";
      	return $where;
      }
      add_filter('posts_where', '__temp_filter_where' );
      
      $edited = get_posts([
      	'posts_per_page' => 15,
      	'date_query'     => ['after'=>'1 weeks ago', 'column'=>'post_modified' ],
      	'post_type'      => ['post','func','hook'],
      	'orderby'        => 'post_modified',
      	'order'          => 'DESC',
      	'suppress_filters' => 0,
      ]);
      remove_filter('posts_where', '__temp_filter_where' );
      
      if( $edited ){
      	foreach( $edited as $pst ){
      		$editted_list[] = '<a href="'. get_permalink($pst) .'">'. esc_html($pst->post_title) .'</a>';
      	}
      }
      
      if( $editted_list ){
      	$out .= '
      	<ul class="li_2 sb_block last_edited">
      		<span class="block__icon"><i class="dashicons dashicons-edit"></i></span>
      		<li>'. implode('</li><li>', $editted_list ) .'</li>
      	</ul>
      	';
      }
  • Добрый день! Странно, я добавил вывод в функции в абсолютно одинаковом виде в шаблоны " страница на реконструкции" и "404" и во втором шаблоне она, почему-то, ничего не выводит? Как такое может быть? Шаблоны абсолютно одинаковые, так текст и картинки только разные.

  • Никак не могу добавить краткое описание и дату sad

    $e_x = '' . esc_html($pst->the_excerpt ) . '';
    $date = apply_filters('the_time', mysql2date($date_m[1], $pst->post_date));

    Строки возвращают пустые поля. Подскажите, пожалуйста

    Ответить4 месяца назад #
    • Kama4485

      не $pst->the_excerpt а $pst->post_excerpt. С датой все норм, должно работать... unknw

      Ответить4 месяца назад #

Здравствуйте, !

Ваш комментарий