Способы построения циклов в WordPress (выводы списка постов в WordPress)

wordpress_plugins[1]Правильное использование нескольких циклов на странице даст вам возможность выводить блоки с нужными записями, сортировать их в нужном порядке и при этом не переживать о нарушении логической структуры страницы и «ловле» различных багов.

Разработчики WordPress предоставляют следующие варианты построения циклов вывода записей:

  1. Стандартный Цикл и цикл на основе query_posts ();
  2. Цикл на основе WP_Query ();
  3. Цикл на основе get_posts ().

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

1. Стандартный Цикл и цикл на основе query_posts ()

Я объединил 2 вида циклов, потому технически они абсолютно одинаковые.

Давайте вспомним, как выглядит стандартный Цикл WordPress:

<?php if( have_posts() ){ while( have_posts() ){ the_post(); ?>

	<div <?php post_class(); ?> id="post-<?php the_ID(); ?>">
		<h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
		<?php the_content(); ?>
	</div>

<?php } // конец while ?>

	<div class="navigation">
		<div class="next-posts"><?php next_posts_link(); ?></div>
		<div class="prev-posts"><?php previous_posts_link(); ?></div>
	</div>
<?php
} // конец if
else
	echo "<h2>Записей нет.</h2>";

Такой код мы можем встретить в файлах index.php, category.php и т.п. Эти файлы отвечают за вывод на странице списка записей. Этот цикл перебирает по очереди посты, которые выводятся на странице и во время перебора, используя Теги Шаблона (предназначенные для использования внутри Цикла), мы можем вывести различные данные поста (заголовок, текст, метаданные и т.д.).

Обратите внимание: в стандартном Цикле мы не указываем никаких данных для выборки записей, а сразу начинаем цикл с if ( have_posts () ){… Это говорит о том, что данные уже существуют и их нужно просто обработать и вывести на экран.

«Уже существующие» данные сохраняются в глобальную переменную $wp_query и для каждого типа страниц WordPress определяются автоматически, т.е. WordPress заранее делает запрос к БД, на основе того какой тип страницы сейчас отображается (категория, метка, статья, постоянная страница и т.д.) и результат запроса записывается в $wp_query, а затем от туда выводится в цикле. Интересно, что такой запрос делается функцией query_posts (), которую мы разберем ниже.

Обычный Цикл WordPress используется для базовых страниц WP (категории, метки, архивы по дате).

Цикл на основе query_posts ()

query_posts () позволяет изменить базовый запрос и вывести нужный нам вариант записей.

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

<?php
global $query_string; // параметры базового запроса
query_posts($query_string.'&cat=-6,-9&order=ASC&posts_per_page=20'); // базовый запрос + свои параметры

[СТАНДАРТНЫЙ ЦИКЛ WORDPRESS]
wp_reset_query(); // сброс запроса
?>

В этом примере мы создали новый запрос к БД, в котором использовали параметры базового запроса + свои параметры: исключили категории 6 и 9 (cat=-6, -9), а также отсортировали записи по порядку (order=ASC) и вывели 20 записей на странице вместо, установленных в настройках 10 (posts_per_page=20). Полный список параметров, которыми можно сформировать нужный нам вывод, смотрите в описании функции query_posts ().

Преимущества такого изменения в том, что если мы, например, изменим количество выводимых записей на странице с 10 (по умолчанию) на 20, то пагинация на странице автоматически подстроиться под это изменение, потому что query_post () меняет данные глобальной переменной $wp_query, а пагинация строиться именно на основе этих данных. Это лишь один из примеров, показывающий что query_posts () и поведение других функций на странице взаимосвязаны.

2. Можно не использовать параметры базового запроса ($query_string), т.е. полностью переписать базовый запрос:

query_posts('cat=-6,-9&order=ASC');

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

Необходимость wp_reset_query ()

Сбрасывать измененный запрос при использовании query_posts () нужно, потому что query_posts () переписывает глобальную переменную $wp_query которая отвечает за некоторые свойства страницы. Давайте посмотрим на примере.

Предположим нам на странице категории 6 (ID категории), нужно вывести данные только поста 9 (ID поста):

<?php
query_posts('p=9');
if(have_posts()){ while(have_posts()){ the_post();
	the_title();
	the_content();
}}
?>

В этом примере мы не сбросили запрос и функция query_posts () переписала глобальную переменную$wp_query. Теперь, если после такого кода, мы проверим какая это страница, а это страница категории (is_category () == true), то мы увидим, что теперь это уже совсем не страница категории, а страница поста (is_single () == true), т.е. следующий код вернет нам «Это страница поста», хотя на самом деле это страница категории:

if( is_category() ) echo 'Это страница категории';
if( is_single() ) echo 'Это страница поста';

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

Когда использовать query_posts ()?

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

Не нужно использовать query_posts () для создания нескольких циклов на одной странице, для вывода в сайдбар списка постов, для создания дополнительного вывода записей и т.п., для этих целей используйте циклы на основе get_posts (). К тому же, обе функции понимают параметры одинаково! Так зачем «платить» больше?..

2. Цикл на основе WP_Query ()

Для вывода записей никак не связанных со страницей или создания множественных циклов можно использовать циклы на основе класса WP_query (). Выглядят они аналогично циклам с использование query_posts (). Для WP_query () используются те же самые параметры (см.в описании функцииquery_posts ()).

Интересно, что WP_query () является ядром функций query_posts () и get_posts (), т.е. обе эти функции работают на основе этого класса.

Пример цикла: выведем все записи из категории 9:

<?php
$query = new WP_Query('cat=9&nopaging=1'); // указываем категорию 9 и выключаем разбиение на страницы (пагинацию)
while($query->have_posts()){ $query->the_post(); ?>

        <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
        <?php the_content(); ?>

<?php } ?>
<?php wp_reset_postdata(); // сбрасываем переменную $post ?>

Пример создания множественных циклов на основе WP_query ():

<?php
// Цикл 1
$query1 = new WP_Query('cat=-1&nopaging=1'); // все посты, кроме категории 1
while($query1->have_posts()){ $query1->the_post();

	// вывод записей

}
wp_reset_postdata();

// Цикл 2
$query2 = new WP_Query('cat=-2&nopaging=1'); // все посты, кроме категории 2
while($query2->have_posts()){ $query2->the_post();

	// вывод записей

}
wp_reset_postdata();

// Цикл 3
$query3 = new WP_Query('cat=-3&nopaging=1'); // все посты, кроме категории 3
while($query3->have_posts()){ $query3->the_post();

	// вывод записей
}
wp_reset_postdata();
?>

Особенность циклов на WP_query () в том, что мы создаем новый объект ($query), который никак не связан с аналогичным глобальным объектом $wp_query и поэтому мы никак не нарушаем структуру текущей страницы.

Так же, мы можем использовать новый объект в других целях, не только для вывода записей, но и для различного рода проверок: например, записи какого типа страницы  используются в этом новом объекте; можем узнать общее количество записей удовлетворяющих запросу ($query->found_posts) и т.д (правда, когда это может пригодится смутно представляю).

Зачем нужно использовать wp_reset_postdata ()

В глобальной переменной $post хранятся данные текущего поста (если показывается страница поста, то данные этого поста). Когда срабатывает часть кода $query->the_post (), то в переменную $postзаписываются данные текущего поста в цикле и в конце цикла в этой переменной остаются данные последнего поста из этого цикла, а нужно чтобы $post всегда содержала данные текущего поста страницы. Т.е. получается до использования цикла $post->ID (ID текущего поста) было равно, допустим, 10, а после срабатывания цикла, та же самая переменная $post->ID уже равна, допустим, 56 (ID последнего поста из цикле), а нужно чтобы она по-прежнему равнялась 10.

wp_reset_postdata () используется как раз для того, чтобы вернуть правильные данные в переменную $post.

Когда использовать WP_query ()?

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

3. Цикл на основе get_posts ()

Самый удобный вариант выводить нужные записи в нужном порядке — это выводить их с помощьюget_posts () (см. описание). get_posts () в 99% случаев полностью заменяет WP_query (): нужно вывести 10 последних постов и сайдбаре или 10 случайных записей в подвале — пожалуйста; нужно вывести все картинки прикрепленные к посту или вывести записи с определенным произвольным полем — get_posts () прекрасно справится с этой задачей.

get_posts () так же как и query_posts () работает на основе класса WP_query () и поэтому передаваемые параметры одинаковые.

1. Пример цикла на основе get_posts (). Выведем 5 записей из рубрики 9:

<?php
global $post; // не обязательно
$args = array('category' => 9); // 5 записей из рубрики 9
$posts = get_posts($args);
foreach( $posts as $post ){ setup_postdata($post);
	// стандартный вывод записей
}
wp_reset_postdata(); // сбрасываем переменную $post
?>

Код выведет именно 5 записей, хотя в аргументах мы указали только номер рубрики. Вызвано это тем, что у функции get_posts () есть параметры по умолчанию (см. описание), о которых нужно помнить. Например, если нам нужно вывести все записи из рубрики 9, то мы должны добавить еще параметр'nopaging' => 1 или 'posts_per_page' => -1 (разницы нет).

Важное отличие get_posts () — функция принимает параметры в виде массива и не понимает параметры в виде строки ('cat=-3&nopaging=1'), как понимают их query_posts () и WP_query ().

Когда использовать get_posts ()

Всегда, когда нужно просто вывести записи из БД в любом месте шаблона. Когда нужно создать несколько циклов. Так как get_posts () принимает те же параметры что и query_posts (), её очень удобно использовать для вывода записей по самым разным критериям.

Выводы

Где и какой из 3-х вариантов циклов использовать:

  • query_posts () — если нужно изменить/подправить стандартный вывод записей на страницах WordPress. Можно использовать 1 раз на странице;
  • get_posts () — если нужно вывести записи из Базы Данных. Можно использовать сколько угодно раз на странице;
  • Класс WP_query () — во всех других случаях когда не подошли query_posts () и get_posts (). Класс WP_query () является ядром query_posts () и get_posts () и может быть использован для каких-либо сложных случаев вывода.


Запись навигация

Top