# 3 СПОСОБА СОЗДАТЬ ЦИКЛ В WORDPRESS – WP_QUERY{}, GET_POSTS(), QUERY_POSTS()

Эта статья предназначена для новичков и тех, кто уже немного знаком с WordPress. Она развеивает мифы о различных типах циклов в WordPress.
Ранее я писал о стандартном цикле WordPress и упоминал о разных вариантах цикла в описаниях функции wp_query
. В этой статье я расскажу о трех вариантах циклов для вывода записей и о плюсах и минусах каждого из них.
Правильное использование нескольких циклов на странице позволит выводить нужные записи, сортировать их в необходимом порядке и не беспокоиться о нарушении логической структуры страницы или появлении различных ошибок.
## Возможные варианты циклов:
1. Стандартный цикл и цикл на основе query_posts()
2. Дополнительный цикл на основе WP_Query()
3. Дополнительный цикл на основе get_posts()
Каждый из этих вариантов удобен в разных ситуациях. Не нужно изучать разные руководства, чтобы использовать каждый вариант, так как они все работают с одними и теми же параметрами. Главное — понять, как и где их применять.
Для лучшего понимания и восприятия того, как работают функции запроса, изучите эту диаграмму:

## 1) СТАНДАРТНЫЙ ЦИКЛ И ЦИКЛ НА ОСНОВЕ QUERY_POSTS()
Я объединил два типа циклов (с query_posts()
и начинающаяся с if(have_posts())
), потому что технически они абсолютно одинаковы.
Вспомним, как выглядит стандартный цикл WordPress:
Записей нет.";
}
?>
Этот код можно найти в файлах index.php
, category.php
и т.д. Эти файлы отвечают за вывод списка записей на странице. Этот цикл проходит по записям, которые отображаются на странице, и с помощью шаблонных тегов мы можем выводить различные данные о записях (название, текст, метаданные и т.д.).
**Примечание:** В стандартном цикле мы не задаем никаких аргументов для получения записей, а сразу начинаем цикл с if(have_posts()){ while(have_posts()){ ... }
. Это означает, что данные уже есть, и их просто нужно обработать и отобразить.
"Уже существующие" данные находятся в глобальной переменной $wp_query
, и для каждой страницы WordPress определяет их автоматически. То есть WordPress делает запрос к базе данных заранее, основываясь на том, какая страница в данный момент отображается (категория, тег, статья, статическая страница и т.д.), и результат этого запроса записывается в $wp_query
. Затем эти данные используются для создания цикла. Интересно, что такой запрос выполняется функцией query_posts()
, которую мы ра��смотрим ниже.
Обычный цикл WordPress используется для стандартных страниц WP (категории, теги, архивы по дате и т.д.).
### ЦИКЛ НА ОСНОВЕ QUERY_POSTS()
query_posts()
позволяет изменять базовый запрос и выводить нужные нам записи.
#### ВАРИАНТ 1
Мы можем изменить базовый запрос (сделать другой запрос и перезаписать данные предыдущего запроса) и, например, убрать лишние категории из вывода или изменить количество выводимых записей, порядок сортировки и т.д.
В этом примере мы создали новый запрос к базе данных, используя параметры базового запроса + наши параметры: исключили категории 6 и 9 (cat=-6, -9
) и отсортировали записи (order=ASC
), а также выводим 20 записей на странице вместо 10 (по умолчанию — posts_per_page=20
).
Смотрите функцию query_posts()
для полного списка параметров, которые можно использовать для генерации нужного вывода.
Преимущество такого изменения в том, что, если мы, например, изменим количество выводимых записей на странице с 10 (по умолчанию) на 20, тогда пагинация на странице автоматически настроится на это изменение, потому что query_posts()
изменяет данные в глобальной переменной $wp_query
, а пагинация строится на основе этих данных. Это всего лишь один пример, показывающий, что query_posts()
и поведение других функций на странице взаимосвязаны.
Рекомендуется изменять базовый запрос WordPress с помощью фильтра pre_get_posts
, а не через query_posts()
.
#### ВАРИАНТ 2
Вы можете не использовать параметры базового запроса (query_string), а полностью переписать базовый запрос:
query_posts( 'cat=-6,-9&order=ASC' );
Однако такой подход по сути сотрет базовый запрос и создаст новый, который может быть составлен некорректно, так что полное переписывание базового запроса не рекомендуется. Лучше попробовать решить задачу другим способом.
### ЗАЧЕМ НУЖЕН WP_RESET_QUERY()?
Необходимо сбросить измененный запрос, когда вы используете query_posts()
, потому что query_posts()
переписывает глобальную переменную $wp_query
, которая отвечает за некоторые свойства страницы. Рассмотрим пример.
Предположим, нам нужно отобразить только запись с ID 9 на странице категории с ID 6:
В этом примере мы не сбросили запрос, и функция query_posts()
переписала глобальную переменную $wp_query
. Теперь, когда мы проверяем, какая это страница (является ли это страницей категории: is_category() == true
), мы видим, что это уже не страница категории, а страница записи: is_single() == true
. Таким образом, следующий код вернет "Это страница записи", хотя на самом деле это категория:
if( is_category() ) echo 'Это страница категории'; // не сработает
if( is_single() ) echo 'Это страница записи'; // сработает
Такое недоразумение может создать много головной боли в будущем.
### КОГДА ИСПОЛЬЗОВАТЬ QUERY_POSTS()?
Когда вам нужно слегка изменить базовый запрос WordPress. В идеале:
- исключить категорию/тег (например, на главной странице).
- изменить направление сортировки.
- ограничить количество записей для вывода.
- исключить определенные записи из категории/тега.
- и т.д.
Опять же, для таких задач лучше использовать фильтр pre_get_posts
.
Никогда не используйте query_posts()
для создания нескольких циклов на одной странице, для вывода списка записей в сайдбаре, для создания дополнительного вывода для записей и т.д. Для этих целей используйте циклы на основе get_posts()
.
## 2) ЦИКЛ НА ОСНОВЕ WP_QUERY()
Чтобы отобразить записи, не связанные с текущей страницей, или создать несколько (дополнительных) циклов, вы можете использовать циклы на основе класса WP_Query
. Они выглядят аналогично циклам query_posts()
и используют те же параметры.
Интересно, что класс WP_Query
является ядром для query_posts()
и get_posts()
, поэтому обе эти функции основаны на этом классе.
Пример цикла: давайте выведем все записи из категории 9:
have_posts() ){
while( $query->have_posts() ){
$query->the_post();
?>
Пример создания нескольких циклов на основе WP_Query()
:
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 (например, 56 — это ID последней записи в цикле), но нам нужно, чтобы она снова равнялась 10.
wp_reset_postdata()
используется именно для того, чтобы вернуть правильные данные в глобальную переменную $post
.
### КОГДА ИСПОЛЬЗОВАТЬ WP_QUERY()?
Если вам нужно отображать записи без воздействия на основной цикл (например, записи в сайдбаре); если нужно создавать несколько запросов. В общем, я не вижу никаких преимуществ у циклов WP_Query()
по сравнению с циклами на основе get_posts()
, поэтому рекомендую использовать get_posts()
вместо WP_Query()
.
## 3) ЦИКЛИ НА ОСНОВЕ GET_POSTS()
Наиболее удобный способ вывода нужных записей в нужном порядке — использовать get_posts()
. get_posts()
чаще всего лучше подходит для вашей задачи, например:
- вам нужно отобразить 10 самых последних записей в сайдбаре.
- нужно вывести 10 случайных записей внизу страницы.
- нужно выв��сти все изображения, прикрепленные к записи.
- нужно вывести записи с определенным мета-полем.
get_posts()
так же, как и query_posts()
, работает на основе класса WP_Query
, так что передаваемые параметры идентичны.
### ПРИМЕР ЦИКЛА НА ОСНОВЕ GET_POSTS()
Давайте выведем 5 записей из категории 9:
9
) );
foreach( $myposts as $post ){
setup_postdata( $post );
// стандартный вывод записи
}
wp_reset_postdata(); // сбрасываем переменную $post
?>
Код выведет ровно 5 записей, даже если мы указали только номер категории в аргументах. Это связано с тем, что get_posts()
имеет предопределенные параметры, о которых нужно помнить. Например, если мы хотим вывести все записи из категории 9, мы должны добавить еще один параметр 'nopaging' => 1
или 'posts_per_page' => -1
(разницы нет).
### КОГДА ИСПОЛЬЗОВАТЬ GET_POSTS()
Всегда, когда вы просто хотите получить записи в любом месте шаблона. Когда хотите создать несколько циклов. Поскольку get_posts()
принимает те же параметры, что и query_posts()
, его очень удобно использовать для вывода записей согласно различным критериям.
## ЗАКЛЮЧЕНИЕ
Где и какой из трех вариантов цикла использовать:
- **get_posts()** — если хотите вывести записи из базы данных. Может быть использован столько раз, сколько нужно на странице.
- **query_posts()** — если нужно изменить/исправить стандартный вывод записей на страницах WordPress. Может быть использован один раз на странице.
- **WP_Query()** — во всех других случаях, когда query_posts()
и get_posts()
не подходят. Класс WP_Query()
является основой query_posts()
и get_posts()
, и может использоваться для любых сложных случаев вывода.
Помните, что параметры одинаковы для любого типа цикла и описаны в классе wp_query
.