Знакомство с WP_Query

WP_Query — это PHP класс, который позволяет получать посты из базы данных по самым разным критериям. Например, мы можем получить посты:

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

WP_Query используется в WordPress для любых запросов связанные с постами. Например, во время генерации любой страницы WP - WP_Query запрос записывается в глобальную переменную $wp_query и кроме данных постов содержит также данные самого запроса - данные о текущей странице. Ни одна генерация базовой страницы WP не обходиться без использования WP_Query.

При построении стандартного цикла WordPress, данные берутся из глобальной переменной $wp_query и выводятся на экран через вспомогательные функции: the_permalink(), the_content().

Кроме списка постов в $wp_query хранится информация о текущем запросе. На основе этой информации WP определяет на какой странице мы сейчас находимся (пост, архив, метка и т.д.). Информация о текущем запросе актуальна только для глобального объекта $wp_query (для объектов в подзапросах эта информация не имеет смысла). Посмотреть что находится в глобально объекте можно так:

print_r( $GLOBALS['wp_query'] );

Часто мы получаем информацию не работая напрямую с этим классом и глобальными переменными - все это скрыто под капотом. А мы пользуемся набором готовых функций - это: условные теги, теги шаблона относящиеся к выводу данных внутри Цикла и другие функции. Почти все условные теги обращаются к этому классу.

Рассмотрим простой запрос:

$query = new WP_Query( [ 'category_name' => 'news' ] );

Так, WordPress сделает запрос в базу данных, чтобы получить записи из категории "news".

Теперь, переменная $query содержит в себе объект с результатами запроса. Обработаем результат с помощью специальных методов:

while ( $query->have_posts() ) {
	$query->the_post();

	the_title(); // выведем заголовок поста
}

wp_reset_postdata(); // ВАЖНО вернуть global $post обратно

Если в цикле используется the_post(), то обязательно после цикла нужно вызвать функцию wp_reset_postdata().

have_posts() проверяет есть ли посты в цикле (в объекте $query). the_post() устанавливает global $post - туда записывается следующий пост из цикла, а также устанавливает другие глобальные переменные - см. setup_postdata(). Все это дает возможность использовать в цикле привычные WP функции без передачи параметров: the_title(), the_content() и т.д.

Подробнее о том как это работает читайте в have_posts() и the_post().

Как не затрагивать global $post

Если нам не нужны стандартные функции, которые работают с global $post, то можно использовать $query->next_post() вместо $query->the_post(). В этом случае глобальная переменная $post не затрагивается:

while ( $query->have_posts() ) {
	$my_post = $query->next_post();

	$url = get_permalink( $my_post );
}

WP_Query через foreach

Если не передать никаких параметров, то запроса не произойдет и будет просто создан объект WP_Query.

Код цикла может выглядеть следующим образом (это тоже самое что get_posts(), только без предустановленных параметров):

// создаем экземпляр
$my_posts = new WP_Query;

// делаем запрос
$myposts = $my_posts->query( [
	'post_type' => 'page'
] );

// обрабатываем результат
foreach( $myposts as $pst ){
	echo esc_html( $pst->post_title );
}

Для лучшего понимания и визуального восприятия работы функций запроса, изучите картинку:

Как работают функции запросов в WordPress
Credit: Andrey Savchenko (rarst.net) / CC-By-SA.

Эта заметка встроена в: WP_Query{}