WordPress: Выводим блоки рубрик с сортировкой по дате последнего поста

Блоки рубрик с сортировкой по дате последнего поста на WordPress Задумка отойти от стандартного вывода последних постов на главной странице этого блога появилась у меня уже очень давно, но я все никак не мог придумать вариант, который бы устроил, да и отсутствие у меня дизайнерских способностей, как обычно, все осложняло. Наконец-то недавно я созрел и решил сделать следующее – вывести блоки рубрик, в которых будет представлен список последних постов из этих рубрик.

Но мне хотелось не просто вывести эти блоки в каком-то произвольно порядке, а чтобы они автоматически сортировались в зависимости от даты последних записей в этих рубриках. Т.е., к примеру, если мой последний пост опубликован в рубрике “CSS”, а предпоследний – в рубрике “jQuery”, то на главной первым будет отображаться блок рубрики “CSS”, вторым, соответственно, “jQuery” и так далее. Т.е. появляется динамичность этих блоков.

Как оказалось, решить подобную задачу не так и сложно. Собственно, готовым php-кодом я и делюсь ниже. Наверняка кому-нибудь да пригодится.

PHP-код

Вот весь основной код с моими комментариями:

<?php
// берем последние 30 постов сайта
$loop = new WP_Query('posts_per_page=30');

if ($loop->have_posts()) {
	// проходимся по каждому из полученных постов
	while ($loop->have_posts()) { $loop->the_post();

		// считываем данные о рубрике поста
		$category = get_the_category($loop->post->ID);

		// получаем идентификатор рубрики и добавляем его в массив
		$array1[] = $category[0]->cat_ID;
	}

	// удаляем из полученного массива повторяющиеся ID рубрик
	$array1 = array_unique($array1);

	// создаем 2-й массив, в котором указываем ID рубрик, последние записи из которых мы хотим вывести
	$array2 = array(1,10,45,107);

	// сравниваем 2 массива, чтобы в списке ID рубрик, полученных из последних 30 постов, остались только те, которые мы указали в массиве $array2, и создаем новый (3-й) массив
	// это действие необходимо для того, чтобы сохранилась сортировка рубрик по дате последнего поста в них
	$array = array_intersect($array1, $array2);
}
// создаем счетчик
$i = 0;

// запускаем цикл, который выводит блоки рубрик
foreach ($array as $cat) { $i++;

	// получаем данные рубрики
	$category = get_category($cat);
?>
	<div class="column<?php /* добавляем класс .odd к каждому нечетному блоку рубрики */ if ($i%2 == true) echo ' odd'; ?>">
		<h2><?php echo $category->name; ?></h2>
	<?php
		// берем последние 7 записей из рубрики
		$loop = new WP_Query('posts_per_page=7&cat=' . $cat);
	?>
	<?php if ($loop->have_posts()) { ?>
		<ul>
		<?php
			// запускаем цикл, который выводит последние записи из рубрики
			while ($loop->have_posts()) { $loop->the_post();
		?>
			<li><?php the_time('d.m.Y') ?> <a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>
		<?php } ?>
	<?php } ?>
		</ul>
		<a href="<?php echo get_category_link($category->cat_ID); ?>">Все статьи рубрики "<?php echo $category->name; ?>"</a>
	</div><!-- .column -->
<?php } ?>

В случае, если вам необходимо, чтобы выводились вообще все рубрики, которые есть на сайте, то в вышеуказанный код внесите следующие изменения:

  1. Удалите эти строки:

    $array2 = array(1,10,45,107);
    $array = array_intersect($array1, $array2);
    
  2. Замените эту строку:

    $array1 = array_unique($array1);
    

    на такую:

    $array = array_unique($array1);
    

Прошу обратить внимание на следующий момент. Если вы в массиве $array2 = array(...) указали определенную рубрику, но ее блок не выводится, значит среди последних 30 постов (которое задано в самой первой строке) не было постов, опубликованных в этой самой рубрике. Значит вам нужно вместо 30 поставить число побольше.

CSS-код

Теперь остается добавить следующие стили, чтобы блоки отображались в 2 столбца:

.column {
	float: right;
	width: 48%;
}
.column.odd {
	clear: both;
	float: left;
}

Ширину (48%) при необходимости поменяйте на свою.

* * *

Всегда важно размещать свой сайт на быстром хостинге, где ваши статические файлы css будут быстро загружаться. Хостинг wordpress можно заказать в компании RX-NAME.

Комментарии (55)

  1. 11 июля 2012 г. в 16:24

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

  2. 11 июля 2012 г. в 17:12

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

    1. Да, я совсем забыл написать про это. В вопросах оптимизации запросов я совсем не разбираюсь, поэтому, конечно, код может быть совсем плохим. Но у меня стояла задача и нужно было как-то ее решить, и как смог, так и сделал.

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

      1. По сути здесь было бы сложно придумать что-то иное. Да, кэширование это конечно хорошо, но всё равно идёт же хоть и раз в определённый период, но приличное количество запросов за раз. В принципе, можно распределить нагрузку… но это такой гемор. В общем, если нужно решить задачу и есть ресурсы, то почему бы и нет.

        1. У меня на сайте (DLE) стоял неудачный модуль древовидных комментариев – 1 запрос на каждый комментари + 2 запроса на построение дерева. Итого на одной из страниц было 190+ запросов (без кеширования). И ничего, сайт вполне себе нормально жил на витруальном хостинге.

          Дима
          Не совсем ожидаемое поведение блоков. Вчера блок программы был первым, сегодня – WordPress. Вводит в заблуждение постоянных посетителей))

          1. Не совсем ожидаемое поведение блоков.

            Ну раз для тебя это так важно, то теперь ты знаешь о том, что они меняются местами =)

            1. Ну я лишь на мгновение смутился)) а у неподготовленного мозга это может вызвать зависание )

            2. Интересная вешь!! Что обновленные блоки будут находиться первее. Спасибо за инструкцию)

          2. Тут всё зависит от хостинга. У меня например виртуальный с соответствующими лимитами.

            У Димы, как я понял, решение сортирует по дате последнего поста. Нюанс и в том, что каких-то категорий в поледних 30 постах может и не быть. Плюс перевесы могут быть в какой-то категории выдаст больше, а в какой-то меньше постов.

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

    2. Пользуйтесь кешированием ;)

    3. А почему бы не воспользоваться каким-нибудь плагином кеширования? Вполне актуально – страница меняется только при добавлении материала, будет сгенерирована раз в день или после изменений. Нагрузка если и будет, то только несколько раз в день.

  3. 26 августа 2012 г. в 11:53

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

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

      1. Все статьи чётко распределены по рубрикам: фильмы, музыка и т.д. А что отвечает за вывод статей в рубриках?
        Если честно, в фильмах я ещё кое-что понимаю, а вот в Вордпресс – нет :)

      2. Проблема была в плагине Simle Tags.

        1. Спасибо что сказал в чем проблема а то я щас тоже буду полностью дизайн и функционал менять и у меня этот плагин Simple Tags стоит )) Буду знать если будут глюки )))

  4. 7 сентября 2012 г. в 23:09

    Дмитрий, подскажите пожалуйста – этот код на пхп надо вставлять в index.php или в другой файл?

    1. 8 сентября 2012 г. в 10:24 / ответ на коммент Андрей

      В index.php, либо home.php.

      1. 8 сентября 2012 г. в 16:07 / ответ на коммент Dimox

        спасибо, попытаемся!

  5. 12 сентября 2012 г. в 10:51

    Да бл* он не умеет вытаскивать подрубрики, т.е так
    -Уроки фотошоп
    -Работа с текстом
    -работа с фото
    Ставлю чтоб вытащить рубрики с Уроки фотошоп, но там нет уроков, они толко в подрубриках , он их не вытаскивает не знаешь как это сделать?

    1. 12 сентября 2012 г. в 10:54 / ответ на коммент Ринат

      WordPress устроен так, что при заходе в рубрику он показывает в том числе и записи из подрубрик.

    2. 12 сентября 2012 г. в 11:10 / ответ на коммент Ринат

      Какую то хрень написал выше,
      Щас изложу по логичнее.
      Есть основная рубрика Уроки фотошоп в ней нет статей, т.к статьи размещаются в подрубриках работа с текстом, работа с фото, и т.д. И я ставлю id рубрики Уроки фотошоп но ничего не выводится , не ну это логично там же нет записей только в подрубриках, а как сделать так чтобы он из этой рубрики Уроки фотошоп выводил записи подрубрик?

      1. 12 сентября 2012 г. в 11:31 / ответ на коммент Ринат

        Может быть записи из этих рубрик не попадают в диапазон, указанный в первой строке кода (30). Попробуй увеличить число.

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

  6. 12 сентября 2012 г. в 11:12

    Ну иили тогда как можно выташить определенную рубрику т.е без твоего кода , отдельно например рубрику Уроки фотошоп с последними 5 записями

    1. 12 сентября 2012 г. в 11:34 / ответ на коммент Ринат
      <?php $loop = new WP_Query('posts_per_page=3&cat=45') ?>
      <?php if ($loop->have_posts()) { ?>
      		<ul>
      	<?php while ($loop->have_posts()) { $loop->the_post(); ?>
      			<li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>
      	<?php } ?>
      		</ul>
      <?php } ?>
      

      3 – количество записей
      45 – рубрика

      1. 12 сентября 2012 г. в 12:10 / ответ на коммент Dimox

        О супер работает щас доделаю и все. Спасибо огромное реально помого. ))

  7. 13 сентября 2012 г. в 23:58

    ты не знаешь как в архиве записей не вытаскивать все записи а записи одной рубрики.
    К примеру надо что бы в архиве записей отображались только записи из рубрики Новости.
    Если знаешь какую нибудь ссылку с реализацией дай пожалуйста )

    1. 14 сентября 2012 г. в 10:09 / ответ на коммент Ринат

      Я же выше дал тебе код.

      1. 14 сентября 2012 г. в 14:08 / ответ на коммент Dimox

        нет это не то

      2. Михаил
        26 февраля 2013 г. в 17:05 / ответ на коммент Dimox

        А как из изменить это кода, чтоб был вывод на главной как у вас, но блоки не менялись местами при новой публикации?

        1. 26 февраля 2013 г. в 17:33 / ответ на коммент Михаил

          В этом случае мою функцию не стоит использовать. Вам нужно сделать несколько циклов c помощью query_posts().

          1. Михаил
            27 февраля 2013 г. в 12:06 / ответ на коммент Dimox

            Ага, я вчера начал так делать. Хочу сделать что то похожее как у вас на главной. Для этого мне нужно сделать несколько таких блоков, я правильно понимаю?

            <div class="post column"> 
            		<div class="title"><h2>заголовок блока</h2>
            		</div> 
            		<ul class="fi"> 
            		    <?php $WP_Query = new WP_Query('cat=90&showposts=5&orderby=date&order=DESC');
                        if ($WP_Query->have_posts()) : while ($WP_Query->have_posts()) : $WP_Query->the_post();?> 
                       <li class="fi"><a href="<?php the_permalink() ?>"><?php the_title(); ?></li>
                       <?php endwhile; endif; ?>  
            		</ul> 
            		<div class="info">
            		<div><a href="/">Все статьи рубрики</a>
            		</div>
            		</div>
            		</div>

            Вроде все нормально работает, кроме одной мелочи, почему то дублируется последняя ссылка из 5 ссылок в блок “Все статьи рубрики”. Может я как то не правильно цикл закрыл или не до закрыл? Причем в исходном коде ее нет, а есть только если нажать “Исследовать элемент”
            Заранее благодарю.

            1. Михаил
              27 февраля 2013 г. в 16:27 / ответ на коммент Михаил

              отбой, ошибка найдена, не закрыл

  8. Лиза
    15 сентября 2012 г. в 05:37

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

    1. 15 сентября 2012 г. в 13:16 / ответ на коммент Лиза

      К сожалению, не знаю, как такое провернуть.

  9. 12 октября 2012 г. в 15:47

    Для Лизы….. http://www.yourinspirationweb.com/en/wordpress-plugin-featured-posts-with-thumbnails-highlighting-your-best-articles/ Плагин Featured Posts with thumbnails.

  10. 13 октября 2012 г. в 20:02

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

        <?php  
        $order = "&orderby=date&order=DESC";  
        $s2 = ' selected="selected"';  
        if ($_POST['select'] == 'title') { $order = "&orderby=title&order=ASC"; $s1 = ' selected="selected"'; $s2 = ''; }  
        if ($_POST['select'] == 'newest') { $order = "&orderby=date&order=DESC"; $s2 = ' selected="selected"'; }  
        if ($_POST['select'] == 'oldest') { $order = "&orderby=date&order=ASC"; $s3 = ' selected="selected"'; $s2 = ''; }  
        if ($_POST['select'] == 'modified') { $order = "&orderby=modified"; $s4 = ' selected="selected"'; $s3 = ''; }  
        ?>  
          
        <form method="post" id="order">  
        Сортировать:  
        <select name="select" onchange='this.form.submit()' style="width:200px">  
        <option value="title"<?=$s1?>>по заголовку</option>  
        <option value="newest"<?=$s2?>>по дате (сначала новые)</option>  
        <option value="oldest"<?=$s3?>>по дате (сначала старые)</option>  
        <option value="modified"<?=$s4?>>по дате изменения</option>  
        </select>  
        </form>  
        <?php query_posts($order); ?>  
    1. 14 октября 2012 г. в 10:38 / ответ на коммент Ринат

      Последнюю строку нужно заменить на такую:

      <?php query_posts($query_string . $order); ?>
      1. 14 октября 2012 г. в 10:42 / ответ на коммент Dimox

        Спасибо как проверю отпишусь ))

      2. 14 октября 2012 г. в 22:19 / ответ на коммент Dimox

        Все супер! Работает! Спасибо выручил как всегда!

  11. Влад
    23 октября 2012 г. в 17:00

    Спасибо за отличное решение. Выводит все в нужном формате, но проблема – выводит одно и то же 4 раза! Подскажите, как от этого избавиться?

    1. 23 октября 2012 г. в 17:14 / ответ на коммент Влад

      Не знаю. У меня ничего не дублируется. Скорее всего, что-то неправильно сделали.

      1. Влад
        23 октября 2012 г. в 17:33 / ответ на коммент Dimox

        Может, вот здесь что-то не так:

        <?php get_header(); ?>
        	<?php if( is_home() && ! is_paged() ) : ?>
        		<?php if( pinboard_get_option( 'slider' ) ) : ?>
        			<?php get_template_part( 'slider' ); ?>
        		<?php endif; ?>
        		<?php get_sidebar( 'wide' ); ?>
        		<?php get_sidebar( 'boxes' ); ?>
        	<?php elseif( ( is_home() && is_paged() ) || ( ! is_home() && pinboard_get_option( 'location' ) ) ) : ?>
        		<?php pinboard_current_location(); ?>
        	<?php endif; ?>
        	<div id="container">
        		<section id="content" <?php pinboard_content_class(); ?>>
        			<?php if( is_category( pinboard_get_option( 'portfolio_cat' ) ) || ( is_category() && cat_is_ancestor_of( pinboard_get_option( 'portfolio_cat' ), get_queried_object() ) ) ) : ?>
        				<?php pinboard_category_filter( pinboard_get_option( 'portfolio_cat' ) ); ?>
        			<?php endif; ?>
        			<?php if (have_posts()) : ?>
        				<div class="entries">
        					<?php while( have_posts() ) : the_post(); ?>
        						<?php get_template_part( 'content-work', get_post_format() ); ?>
        					<?php endwhile; ?>
        				</div><!-- .entries -->
        				<?php pinboard_posts_nav(); ?>
        			<?php else : ?>
        				<?php pinboard_404(); ?>
        			<?php endif; ?>
        		</section><!-- #content -->
        		<?php if( 'no-sidebars' != pinboard_get_option( 'layout' ) && 'full-width' != pinboard_get_option( 'layout' ) && ! is_category( pinboard_get_option( 'portfolio_cat' ) ) && ! ( is_category() && cat_is_ancestor_of( pinboard_get_option( 'portfolio_cat' ), get_queried_object() ) ) ) : ?>
        			<?php get_sidebar(); ?>
        		<?php endif; ?>
        		<div class="clear"></div>
        	</div><!-- #container -->
        <?php get_footer(); ?>
        1. Влад
          23 октября 2012 г. в 17:33 / ответ на коммент Влад

          А ваше решение, как раз в content-work.php

  12. Андрей
    25 января 2013 г. в 11:52

    Извините, что не по теме, но все-таки…

    У меня почему-то не работает такая простая, казалось бы, штука: post_is_in_descendant_category?

    Я пока пользуюсь этой конструкцией:

    if (in_category (array ( ’87’, ’99’ ))) {

    include (TEMPLATEPATH.’/loop-flower.php’);

    } elseif (in_category (array ( ’96’, ‘104’ ))) {

    include (TEMPLATEPATH.’/loop-care.php’);

    } else {

    include (TEMPLATEPATH.’/loop-single.php’);

    }

    Но по при увеличении количества дочерних рубрик это перестанет быть удобным. Подскажите, что не так? Как правильно прописать код?

  13. 20 апреля 2013 г. в 10:36

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

  14. 16 мая 2014 г. в 23:10

    Дмитрий, добрый день!
    Прочитав вашу статью в принципе все понятно, но когда я вставляю ваш код в index.php ничего не меняется.
    Код index.php

    <?php get_header(); ?>
    
    <div class="main <?php echo alx_layout_class(); ?>">
    	<div class="main-inner group">
    		
    		<section class="content">
    		
    			<?php get_template_part('inc/page-title'); ?>
    			
    			<div class="pad group">
    				<?php get_template_part('inc/featured'); ?>
    				
    				<?php if ( have_posts() ) : ?>
    				
    					<div class="post-list group">
    						<?php $i = 1; echo '<div class="post-row">'; while ( have_posts() ): the_post(); ?>
    						<?php get_template_part('content'); ?>
    						<?php if($i % 2 == 0) { echo '</div><div class="post-row">'; } $i++; endwhile; echo '</div>'; ?>
    					</div><!--/.post-list-->
    				
    					<?php get_template_part('inc/pagination'); ?>
    					
    				<?php endif; ?>
    				
    			</div><!--/.pad-->
    			
    		</section><!--/.content-->
    		
    		<?php get_sidebar(); ?>
    		
    	</div><!--/.main-inner-->
    </div><!--/.main-->
    
    <?php get_footer(); ?>

    Огромная просьба подскажите пожалуйста в какое место нужно вставить Ваш код или как его преобразовать, чтобы вывести 4 блока (4 рубрики) на галвной.

    Заранее спасибо!

    1. Вставьте вместо кода <div class="pad group">...</div><!--/.pad-->.

      Если у вас в шаблоне есть файл home.php, тогда вставлять нужно в него, а не в index.php.

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

        1. Мне больше нечего посоветовать.

  15. Павел
    24 апреля 2016 г. в 16:32

    Привет, твой код отлично работает для стандартной таксономии category.
    А если мне нужно делать почти тоже самое только из своей таксономии ?

    1. 25 апреля 2016 г. в 17:38 / ответ на коммент Павел

      С таксономиями вообще не дружу.

  16. Александр
    28 августа 2016 г. в 09:08

    Интересно.
    А нет у вас статейки как в 3-х блоках вывести 3 отдельные рубрики?

  17. 28 октября 2020 г. в 19:59

    Отличная статья, и отлично закомментированный код. Его просто и понятно читать. Респект автору за четкую работу – таких мало. Все четко и работает как нужно. Короч я такое давно хотел сам сделать – только руки не доходили. СПАСИБО!

  18. 1 ноября 2020 г. в 10:12

    Привет, спасибо за отличный код. Работает на ура. Как то пытался такой написать только подходил с другой стороны – вначале находил рубрики, все работало так же, за исключением того что обновленная рубрика не двигалась на первое место. А это не удобно.

    Есть вопрос кстати. Сайт как известно должен быть красивым, а у меня публикуется примерно 1-2 к статей в день. И порой с одной рубрики а порой с разных. В итоге блок статей может быть просто разной длины. Тут не угадать. Я закрыл вопрос тем, что с помощью CSS скрыл все блоки после 17 го – то есть показываю только 17 новых статей из разных рубрик. Т е в каждой рубрике по одной статье. А как сделать такое без CSS, просто выводить 17 результатов ПОСЛЕ всех фильтров. Заранее спасибо!

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

Жирный текст

Ссылка

Цитата

Внутристрочный код

CSS-код

HTML-код

JavaScript-код

PHP-код