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

Перелинковка статей в WordPress (предыдущие записи из категории)

Это продолжение поста о перелинковке статей.

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

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

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

Почти, такую же функцию я публиковал в комментариях на сайте Dimox.name здесь. Почему "почти"? Потому что, эта функция обладает рядом преимуществ над той, что была опубликована на Dimox.name, а именно:

  1. Можно задавать формат вывода, благодаря чему её очень просто внедрить в любой шаблон;

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

  3. Функция не использует тяжелую функцию самого WordPress get_posts()

  4. К каждому тегу ссылки добавляется классы li1 и li2, чтобы легко можно было раскрасить список в зебру.

  5. Можно включить кэширование. Подробнее об этом ниже.

  6. Список сортируется по дате, а не по ID, т.е. если запись была опубликована задним числом она будет выводится как нужно.

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

А вот, собственно, и код, который нужно поместить в ваш файл шаблона functions.php.

/**
 * Предыдущие записи из рубрики (относительно текущей записи) + кольцевая перелинковка
 * Параметры передаваемые функции. В скобках указано дефолтное значение.
 *
 * @param int    $post_num (5)    количество ссылок
 * @param string $format   ('')   {thumb} {date:j.M.Y} - {a}{title}{/a} ({comments})
 * @param string $cache    ('')   включить кэш (по умолчанию выключен). Пишем 1, чтобы включить
 * @param string $list_tag (li)   тег списка
 * @param bool   $echo     (true) Выводить на экран или возвращать для обработки (false)
 *
 * @version 1.0
 */
function kama_previous_posts_from_cat( $args ){
	global $post, $wpdb;

	$args = (object) wp_parse_args( $args, array(
		'post_num' => 5,
		'format'   => '',
		'cache'    => true,
		'list_tag' => 'li', // тег
		'echo'     => true,
	) );

	$cache_key  = md5( __FUNCTION__ . $post->ID );
	$cache_flag = __FUNCTION__;

	if( $args->cache && $cache_out = wp_cache_get($cache_key, $cache_flag) ){
		if( $args->echo )
			return print( $cache_out );
		return $cache_out;
	}

	$cat = get_the_category( $post->ID );
	$cat_id = (int) $cat[0]->term_id;

	$same_join = "SELECT ID, post_title, post_date, comment_count, guid
	FROM $wpdb->posts p
		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)";

	$same_and = $wpdb->prepare( "AND tax.term_id = %s AND tax.taxonomy = 'category' AND p.post_status = 'publish' AND p.post_type = 'post'", $cat_id );

	// пробуем получить предыдущие записи
	$sql = "$same_join WHERE p.ID < $post->ID $same_and ORDER BY p.post_date DESC LIMIT ". intval($args->post_num);

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

	$count_res = count($res);

	// если количество меньше нужного, делаем 2-й запрос
	if ( ! $res || $count_res < $args->post_num ){
		$exclude = $post->ID;

		if( $res ) foreach( $res as $id ) $exclude .= ','. $id->ID;

		$post_num = (int) $args->post_num - $count_res;

		$sql = "$same_join WHERE p.ID NOT IN ($exclude) AND p.ID != {$post->ID} $same_and ORDER BY p.post_date DESC LIMIT ". intval( $post_num );

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

		$res = array_merge( $res, $res2 );
	}
	if ( ! $res )
		return false;

	if ( $args->format )
		preg_match( '!{date:(.*?)}!', $args->format, $date_m );
	if ( false !== strpos($args->format, '{thumb}') )
		$add_thumb = 1;

	$out = $x = '';
	foreach( $res as $pst ){
		$x = ($x == 'li1') ? 'li2' : 'li1';
		$a1 = '<a href="'. get_permalink($pst->ID) .'" title="'. esc_attr($pst->post_title) .'">';
		$a2 = "</a>";

		if ( $args->format ){
			$date      = apply_filters( 'the_time', mysql2date($date_m[1], $pst->post_date) );
			$com_count = $pst->comment_count == 0 ? '' : $pst->comment_count;

			$formated = str_replace( $date_m[0], $date, $args->format );
			$formated = str_replace( '{title}', esc_html($pst->post_title), $formated );
			$formated = str_replace( '{a}', $a1, $formated );
			$formated = str_replace( '{/a}', $a2, $formated );
			$formated = str_replace( '{comments}', $com_count, $formated );

			// есть миниатюра
			if( isset($add_thumb) ){
				$thumb = get_the_post_thumbnail( $pst->ID, 'thumbnail' );
				$formated = str_replace('{thumb}', $thumb, $formated );
			}
		}
		else
			$formated = $a1 . esc_html( $pst->post_title ) . $a2;

		$out .= apply_filters( 'kama_previous_posts_from_cat__append_out', 
					"\n<$args->list_tag class=\"$x\">$formated</$args->list_tag>",
					$args, $formated, $x, $pst );
	}

	if( $args->cache )
		wp_cache_add( $cache_key, $out, $cache_flag );

	if( $args->echo )
		return print $out;

	return $out;
}

После того, как код, успешно, скопирован в файл темы functions.php, в том месте где мы хотим вывести предыдущие записи из текущей категории вызываем функцию так:

<ul>
	<?php kama_previous_posts_from_cat('post_num=5');  ?>
</ul>

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

Важно! Вызов будет работать корректно только в файле темы, отвечающем за вывод постов, обычно это single.php.

Расширенное использование

Для настройки формата вывода используйте

В параметре format можно использовать следующие шорткоды:

  • {thumb} - миниатюра записи (она должна быть установлена для записи);
  • {comments} - покажет количество комментариев у статьи;
  • {title} - заголовок статьи;
  • {date:j.M.Y} - дата в формате j.M.Y (11.Апр.2010);
  • {a} и {/a} - тег ссылки. Открывается и закрывается.

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

<ul>
<?php
kama_previous_posts_from_cat( array(
	'post_num' => 5,
	'format' => '{a}{title}{/a} ? {date:j.M.Y} // {comments}',
) );
?>
</ul>
// выведет список в формате - <li class='li1'><a href='http://ссылка' title='Заголовок статьи'>Заголовок статьи</a> ? дата // количество комментариев</li>
Использование кэша

Кэширование по умолчанию включено, но пользу от использования можно будет ощутить, если функция вызывается несколько раз или если включен плагин объектного кэширования: WP File Cache, SJ Object Cache и другие...

Тег списка

Можно изменить тег списка li на любой другой, например div

<?php kama_previous_posts_from_cat('post_num=5&list_tag=div'); ?>

// выведет 5 ссылок в формате - <div class='li1'><a href='http://ссылка' title='Заголовок статьи'>Заголовок статьи</a></div> .

Изменения

Версия 1.0.

  • Добавил шорткод {thumb} в параметр format
  • Теперь все аргументы передаются в первом параметре функции, в виде массива или строки.
127 комментов
Полезные 1 Вопросы 1 Все
  • Velimudr freelance.ru/tim4ik

    Добрый день, Тимур.
    У меня вопрос; Нужно выводить 6 записей в хронологическом порядке (по времени от текущей статьи в порядке убывания) не с какой-то определённой категории, а с любой.
    Как сделать такой вывод?

    1
    Ответить4.4 года назад #
  • добрый день, я в коде не спец и задам парочку глупых вопросов:

    1: Можно сделать перелинковку в обе стороны ? т.е например 2 назад и 2 вперед ?

    2: У меня есть несколько вложенных категорий. Я хочу чтобы линковка была только по родительской категории. Это возможно ?

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

      Все возможно, но конкретно код я вам не дам - времени нет... pardon

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

    Есть у кого этот код с добавлением миниатюр записей? Спасибо!

    PS Найденным в комментариях решениям не смог дать жизни. Т.к. не очень понятны способы их употребления для не разбирающегося!

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

      Добавил шорткод {thumb} в параметр format, тестани плз все ли норм работает. Версия 1.0

      1
      Ответить2 года назад #
      • Maksim

        Да миниатюра подставляется! Спасибо!

        Огонь спасибо Kama!!! Вот что вышло

        Ответить2 года назад #
  • @ Иван

    как убрать знак "жирная точка, кружок" перед названием выводимого поста . Ну выводит как бы маркированный список

    Ответить11 мес назад #
  • Давно пользуюсь вашим решением, можно ли вместо $out .= вставить туда ссылку на шаблон моей карточки записи которую я использую в архивах со всеми полями и прочим ? Просто каждый раз переписывать этот код долго.

    Ответить8 мес назад #
    • Kama7630

      Добавил хук туда, юзай так:

      add_filter( 'kama_previous_posts_from_cat__append_out', 'prev_posts__append_out', 10, 5 );
      function prev_posts__append_out( $out, $args, $formated, $x, $pst ){
      	// тут можешь вернуть что нужно
      	return "\n<$args->list_tag class=\"$x\">$formated</$args->list_tag>";
      }
      Ответить8 мес назад #
  • Здравствуйте Kama, помогите, пожалуйста, встроить Вашу функцию кольцевой перелинковки в этот код:

    <?php
    
    $related_count_mod = root_get_option( 'structure_single_related' );
    $related_yarpp_enabled = apply_filters( 'root_yarpp_enabled', false );
    
    if ( ! empty( $related_count_mod  ) && ! $related_yarpp_enabled ) {
    
    	$related_count = 6;
    	if ( is_numeric($related_count_mod) && $related_count_mod > -1 ) {
    		if ( $related_count_mod > 50 ) $related_count_mod = 50;
    		$related_count = $related_count_mod;
    	}
    
    	// подготавливаем категории
    	$category_ids = array();
    	$categories = get_the_category($post->ID);
    	if ( $categories ) {
    		foreach( $categories as $_category ) {
    			$category_ids[] = $_category->term_taxonomy_id;
    		}
    	}
    
    	// делаем первый запрос
    	$related_articles = get_posts(array(
    		'category__in'      => $category_ids,
    		'posts_per_page'    => $related_count,
    		'orderby'           => 'rand',
    		'post__not_in'      => array($post->ID),
    	));
    
    	// если не хватило, добираем рандом
    	if ( count($related_articles) < $related_count ) {
    
    		// сколько осталось постов
    		$delta = $related_count - count($related_articles);
    
    		// убираем текущий пост + уже выведенные
    		$post__not_in = array( $post->ID );
    		foreach ( $related_articles as $article ) {
    			$post__not_in[] = $article->ID;
    		}
    
    		$related_articles_second = get_posts(array(
    			'posts_per_page'    => $delta,
    			'orderby'           => 'rand',
    			'post__not_in'      => $post__not_in,
    		));
    
    		// если все ок, объединяем
    		if ( ! empty( $related_articles_second ) ) $related_articles = array_merge( $related_articles, $related_articles_second );
    	}
    
    	if (!empty($related_articles)) {
    
    		?>
    
    		<div class="b-related">
    
    			<div class="b-related__header"><span><?php echo apply_filters( 'root_related_title', __('Related articles', 'root') ) ?></span></div>
    
    			<div class="b-related__items">
    
    				<?php foreach ($related_articles as $post) {
    					setup_postdata($post); ?>
    
    					<?php get_template_part('template-parts/posts/content', 'card-without-micro'); ?>
    
    				<?php }
    				wp_reset_postdata(); ?>
    
    			</div>
    		</div>
    
    		<?php
    	}
    
    } else {
    
    	/**
    	 * If yarpp enabled
    	 */
    	if ( function_exists( 'related_posts' ) && $related_yarpp_enabled ) {
    		related_posts();
    	}
    
    }

    Буду очень признателен, поскольку сделать самому не хватает знаний.

    Ответить2 мес назад #
  • Здравствуйте, а можно сделать заголовки в статьях более короткие? обычно я для этого использую функцию <?php echo get_short_title(30); ?> но как эту функцию вывода короткого заголовка встроить в данный код непонятно.

    Ответить25 дней назад #
Здравствуйте, !     Войти . Зарегистрироваться