Использование WP_Query в WordPress

Если Вы работали с WordPress некоторое время, вы должны знать как трудно было раньше создавать списки записей на основе большого количества критериев и в то же время в соответствии со стандартами WordPress. Но за последние нескольких лет платформа прошла долгий путь. И сейчас, с помощью мощного класса WP_Query, мы можем создавать списки сообщений ни в чем себя не ограничивая.

Что такое WP_Query?

Класс WP_Query является одной из важнейших частей в движке WordPress. Среди прочего, он определяет запросы, которые вам необходимы на любой странице и выводит сообщения в соответствии с заданными критериями. Он также сохраняет много информации о запросах которые делает, что помогает при оптимизации страниц (и устранении ошибок).

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

Безопасность

На протяжении всего нашего взаимодействия с этим объектом, мы указываем лишь параметры и используем функции для достижения нашей цели. Внутренние объекты сами заботятся о многих проблемах, таких как защита от SQL-инъекций и проверка использования правильного типа данных.

Простота

При использовании этого объекта нам не нужно изучать особенности нашей базы данных. Поскольку мы используем массив, чтобы передавать наши параметры, нет нужды вручную писать запросы с join или вложенные запросы, нужно просто создать массив аргументов и экземпляр класса!

Модульность

WP_Query позволяет избежать использования SQL-запросов в коде, класс использует ассоциативный массив в качестве аргумента. Это позволяет получить множество преимуществ: вы можете объединить аргументы из разных мест кода, запустить массив функций и управлять ими всевозможными способами.

Итак, начнем!

"Стандартный" цикл в WordPress

Давайте посмотрим вначале на обычный цикл, и затем создадим такой же цикл, используя WP_Query. Давайте предположим, что мы создаем файл category.php для своей темы.

 <?php
 if(have_posts()) :
  while(have_posts()) :
 the_post();
 ?>
 <h1><?php the_title() ?></h1>
 <div class='post-content'><?php the_content() ?></div>
 <?php
 endwhile;
 else :
 ?>
 Упс, записей не найдено!
 <?php
 endif;
 ?>

То же цикл, используя WP_Query:

 <?php
 $args = array('cat' => 4);
 $category_posts = new WP_Query($args);
 
 if($category_posts->have_posts()) :
 while($category_posts->have_posts()) :
 $category_posts->the_post();
 ?>
 <h1><?php the_title() ?></h1>
 <div class='post-content'><?php the_content() ?></div>      
 <?php
 endwhile;
 else:
 ?>
 Упс, записей не найдено!
 <?php
 endif;
 ?>

Как вы можете видеть, на первый взгляд нет большой разницы! Давайте рассмотрим его подробнее:

Построение запросов

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

Создание экземпляра класса и запросов для сообщений

С помощью экземпляра класса и массива аргументов, WP_Query будет пытаться получить указанные сообщения.

Создание цикла

Вы можете использовать любые обычные функции, только не забудьте использовать их в качестве методов объекта:

Вместо have_posts(), используйте $category_posts->have_posts().
Вместо the_post(), используйте $category_posts->the_post().

После того как вы сделали всё что указано выше, вы можете использовать любые теги шаблонов, которые мы знаем и любим.

Если вы посмотрите на это подробнее, то вы увидите, что глобальный объект $post также доступен. Это означает, что если вы используете пользовательский цикл, что-нибудь может пойти не так. Обязательно сохраните первоначальное значение объекта $post и восстановите его после цикла.

 <?php
 $temp_post = $post; // Storing the object temporarily
 $my_query = new WP_Query();
 while($my_query->have_posts()) {
 // Loop in here
 }
 $post = $temp_post; // Restore the value of $post to the original
 ?>

Идем дальше...

Легкость, с которой мы можем создавать циклы очевидна, но как на самом деле создавать запросы для записей? Позвольте мне показать вам распространенный метод, который часто используют при создании слайдеров в коммерческих темах.

Очень часто пользователи вашей темы хотят видеть на своих сайтах великолепно выглядящие слайдеры, но они могут быть немного ленивы при создании контента. Многие пользователи также хотят показать будущие записи, которые планируется опубликовать. Давайте создадим запрос для получения предстоящих (т.е. неопубликованых) сообщений, которые имеют изображение.

 <?php
 $args = array(
 'post_status' => 'future',
 'meta_query' => array(
 array(
 'key' => '_thumbnail_id',
 'value' => '',
 'compare' => '!='
 )
 )
 );
 $slider_posts = new WP_Query($args);
 ?>
 
 <?php if($slider_posts->have_posts()) : ?>
 
 <div class='slider'>
 <?php while($slider_posts->have_posts()) : $slider_posts->the_post() ?>
 <div class='slide'>
 <?php the_post_thumbnail() ?>
 </div>
 <?php endwhile ?>
 </div>
 
 <?php endif ?>

Короткий и совершенно понятный код - просто и красиво.

Значения по умолчанию

Вы, возможно, заметили, что я не уточнил количество необходимых записей в моём запросе. А сколько сообщений в списке? И что за статус поста в первом запросе, который мы сделали?

Значения по умолчанию устанавливаются для многих из наиболее распространенных аргументов. Вот несколько, которые вы не обязаны указывать, если только вы не хотите изменить их:

posts_per_page
По умолчанию используется значение, указанное в параметрах сайта о количестве сообщений на странице.

post_type
По умолчанию используется post.

post_status
По умолчанию используется publish.

Вы можете найти полный список параметров в документации!

Массивы

Во многих случаях вам нужно будет указать несколько значений, которые может принимать аргумент. И WP_Query позволяет использовать массивы, чтобы сделать вашу жизнь проще. Вот несколько примеров:

Вы можете использовать массив для post_status, чтобы получить сообщения с различными статусами. Обратите внимание, что вы можете использовать строку any, чтобы получить сообщения со всевозможными статусами.

Если вы используете пользовательские типы сообщений, вы будете рады услышать, что вы можете использовать массив для значений параметра post_type также.

Для таксономии параметры типа category__in, tag__in и так далее, вы можете использовать массив для указания множества значений.

Обработка Таксономии

WP_Query достаточно хорош, чтобы предложить простой способ сделать сложные запросы к таксономии. Это особенно полезно для веб-сайтов с сложными  настройками для коммерческих тем и с большим набором функций. Используемый механизм называется tax_query. Давайте посмотрим на примере.

Скажем, у вас есть сайт: Все о кино. Вы храните фильмы в пользовательском типе записей "movies"; у вас также есть тип записей для жанра, пользовательский тип записей для актеров, и вы используете обычную категорию, чтобы указать, насколько хороший фильм. Давайте найдем все фильмы жанра "Action" в главной роли с Брюсом Уиллисом, которые не являются "Bad":

 <?php
 $args = array(
 'post_type' => 'movie',
 'tax_query' => array(
 'relation' => 'AND',
 array(
 'taxonomy' => 'category',
 'field' => 'slug',
 'terms' => array('bad')
 'operator' => 'NOT IN'
 ),
 array(
 'taxonomy' => 'genre',
 'field' => 'slug',
 'terms' => array('action')
 ),
 array(
 'taxonomy' => 'actor',
 'field' => 'slug',
 'terms' => array('Bruce Willis'),
 )
 )
 );
 ?>

Хотя это пример с хардкодом, и может быть полезен только для людей, которые любят "Крепкий орешек", но не трудно понять как расширенный фильтр может быть построен, чтобы позволить пользователям фильтровать ваш контент любым образом, как они хотят.

Узнать больше о использовании параметров таксономии можно в соответствующем разделе документации.

Работаем с метаданными

Вы уже видели, что WP_Query отлично справляется с мета-данными - мы использовали meta_query во втором примере, когда строили слайдер с записями, которые имеют изображения.

Представим, что мы создаем тему WordPress, которая будет использоваться для сайта сдающего квартиру(ы) в аренду. Мы будем хранить квартиры в пользовательском типе записей и использовать мета-данные для хранения дополнительной информации. Таким образом, мы можем легко получать, например, все квартиры, которые могут вместить четырех или более человек, или те у которых есть балкон, или только квартиры на сутки с джакузи.

 <?php
 $args = array(
 'post_type' => 'apartment',
 'meta_query' => array(
 'relation' => 'AND',
 array(
 'key' => 'persons',
 'value' => '4',
 'compare' => '>=',
 'type' => 'NUMERIC'
 ),
 array(
 'key' => 'balcony',
 'value' => '1',
 'type' => 'BINARY',
 'compare' => '='
 ),
 array(
 'key' => 'sutki',
 'value' => '1',
 'type' => 'BINARY',
 'compare' => '='
 )
array(
 'key' => 'jacuzzi',
 'value' => '1',
 'type' => 'BINARY',
 'compare' => '='
 )
 )
 );
 ?>

Чтобы узнать больше о параметрах, которые можно использовать, просто зайдите в раздел Custom Field Parameters в документации по WP_Query.

Методы и свойства

Как только Вы сделали запрос, можно вытянуть много информации из Вашего объекта. Вы можете найти полный список "Методов и свойств" в документации. Вот те, которые я предпочитаю использовать чаще всего:

$query
Показывает строку запроса, которая передается в объект $wp_query. Это очень полезно для устранения неполадок в некоторых случаях.

$query_vars
Показывает ассоциативный массив аргументов, которые вы передали. Если вы делаете много смешиваний и сопоставлений перед передачей аргументов, этот инструмент может быть полезным, чтобы проверить, что все передано правильно.

$post
Содержит запрошенные записи из базы данных.

$found_posts
Удобная вещь, которая показывает общее число найденных элементов (без ограничения установленного аргументом posts_per_page).

С большой силой приходит большая ответственность

WP_Query дает вам большие возможности, но у него есть свои недостатки. Многие люди "сходят с ума", когда они понимают, как легко можно вызывать запросы повсюду.

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

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

Перевод статьи с http://wp.smashingmagazine.com


Если у Вас возникли вопросы, то для скорейшего получения ответа рекомендуем воспользоваться нашим форумом

You have no rights to post comments