Почему опасно использовать 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 страницу.