Почему опасно использовать query_posts()
query_posts() предназначена для самого WordPress и должна использоваться только для изменения основного запроса WordPress на базе которого потом строится Цикл WordPress.
Поэтому, когда нужно создать еще один запрос (цикл), нужно использовать get_posts() или WP_Query. Эти функции могут принимать все те же параметры что и query_posts().
Пример использования get_posts() вместо query_posts():
<?php
$args = array( 'posts_per_page' => 3 );
$lastposts = get_posts( $args );
foreach( $lastposts as $post ){
setup_postdata( $post );
?>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php
the_content();
}
wp_reset_postdata();
Пример использования WP_Query вместо query_posts():
$args = array( 'posts_per_page' => 3 );
$query = new WP_Query( $args );
while ( $query->have_posts() ) {
$query->the_post();
the_title(); // выведем заголовок поста
}
wp_reset_postdata();
Почему query_posts() нужно использовать очень аккуратно?
Основной запрос WordPress — это запрос, который выполняется до вывода какого-либо текста на страницу (на раннем этапе). Параметры такого запроса собирает сам WP опираясь на: запрошенный URL; настройки ЧПУ (постоянных ссылок) и др. Так WordPress определяет сколько записей показать на странице, записи из какой рубрики показывать и т.д.
Дополнительный запрос — это тот, который создается пользователем (темой, плагином) и выполняется дополнительно к основному. Например: Вывод в сайдбаре списка популярных записей; Вывод комментируемых записей.
Так вот, если использовать query_posts() для создания дополнительных запросов (циклов), то могут появится ошибки из-за которых будет рушится структура кода, так как повторный вызов query_posts() переписывает базовый запрос WP, на основе которого определяется тип текущей страницы (запись, рубрика), определяется сколько записей показывать на странице (пагинация) и многое другое.
Разница между query_posts() и WP_Query в том, что query_posts() создает новый WP_Query объект и связывает его с глобальной переменной $wp_query, тогда как get_posts() или WP_Query() создает новый WP_Query объект, без изменения каких-либо глобальных данных.
Давайте рассмотрим на примере:
// Пример 1: Дополнительный запрос с помощью query_posts
query_posts( $args );
while ( have_posts() ) {
the_post();
the_title(); // вывести название
}
// Пример 2: Дополнительный запрос с помощью WP_Query
$second_query = new WP_Query( $args );
while ( $second_query->have_posts() ) {
$second_query->the_post();
the_title();
}
Тут, первый пример переписывает глобальные переменные $wp_query, $post, $posts, а второй работает автономно и ничего глобального не трогает.
Чтобы более детально понять разницу прочитайте заметку: 3 способа построения циклов в WordPress.
Если вы по каким-то причинам вынуждены использовать query_posts(), то после цикла обязательно используйте wp_reset_query() - сбрасывает глобальные переменные запроса на начальные.
Если не сбросить цикл с помощью wp_reset_query(), то, например, может сломаться пагинация (это самый яркий пример из жизни) — это когда первая страница работает, а остальные показывают 404 страницу.