Главная WordPress

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. Спасибо за статью, самому в этом деле сложнова-то разобраться.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        <?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); ?>  
  10. Спасибо за отличное решение. Выводит все в нужном формате, но проблема — выводит одно и то же 4 раза! Подскажите, как от этого избавиться?

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

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

        <?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(); ?>
  11. Извините, что не по теме, но все-таки…

    У меня почему-то не работает такая простая, казалось бы, штука: 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');

    }

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

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

  13. Дмитрий, добрый день!
    Прочитав вашу статью в принципе все понятно, но когда я вставляю ваш код в 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 рубрики) на галвной.

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

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

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

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

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

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

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