Пользовательские запросы WordPress — использование класса WP_Query

Опубликовано: 2021-02-06

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

Давайте посмотрим, как можно использовать класс WP_Query !

Пользовательские запросы

ПРИМЕЧАНИЕ. В этой статье предполагается, что у вас есть некоторые знания PHP и MySQL/MariaDB, а также вы знакомы с работой с WordPress.

Какую бы страницу вы ни посетили, WordPress запускает так называемый «основной запрос» для отображения содержимого. Поэтому, когда вы посещаете страницу, такую ​​как, например, представление категории, объект WP_Query создается за кулисами и извлекает все необходимые данные из базы данных для отображения страницы.

Что в основном делает WP_Query , так это предлагает вам возможность извлекать контент из базы данных вашего веб-сайта без использования SQL-запросов.

Для этого все, что нам нужно сделать, это определить аргументы, соответствующие нашим потребностям, и новый объект WP_Query будет создан и преобразован в SQL-запрос.

Пример использования WP_Query

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

Для целей этого примера мы активировали тему Twenty Twenty и создали 2 сообщения в категории «Категория 1» и 2 сообщения в категории «Услуги».

Кроме того, мы создали настраиваемый шаблон просмотра категорий для сообщений «Категория 1». Слаг этой категории — «category-1», поэтому файл в папке темы должен быть category-CATEGORYSLUG.php , который в нашем случае — category-category-1.php .

Пожалуйста, вставьте следующее в файл category-category-1.php .

 <?php /*** Custom Category 1 Template */ get_header(); ?> <main role="main"> <section class="site-content"> <div role="main"> <?php if ( have_posts() ) : ?> <header class="archive-header"> <h3 class="archive-title">Category: <?php single_cat_title( '', true ); ?></h3> </header> <?php while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; endif; ?> </div> </section> </main> <?php get_sidebar(); ?> <?php get_footer(); ?>

Перед циклом мы используем метод have_posts , чтобы определить, есть ли еще доступные сообщения в цикле.

the_post() необходим для того, чтобы цикл повторял сообщения и сообщал WordPress о переходе к следующему сообщению в массиве сообщений.

На данный момент внешний вид категории ( https://mycompanyname.com/category/category-1/ ) будет выглядеть примерно так:

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

Чтобы увидеть свойства объекта запроса, которые WordPress создал для этого представления, мы можем просто добавить эту строку в наш код после endif; утверждение.

 var_dump ( $wp_query->query_vars );

Теперь, если вы обновите свою страницу, вы увидите эту информацию в списке сообщений:

 array(63) { ["category_name"]=> string(10) "category-1" ["error"]=> string(0) "" ["m"]=> string(0) "" ["p"]=> int(0) ["post_parent"]=> string(0) "" ["subpost"]=> string(0) "" ["subpost_id"]=> string(0) "" ["attachment"]=> string(0) "" ["attachment_id"]=> int(0) ["name"]=> string(0) "" ["pagename"]=> string(0) "" ["page_id"]=> int(0) ["second"]=> string(0) "" ["minute"]=> string(0) "" ["hour"]=> string(0) "" ["day"]=> int(0) ["monthnum"]=> int(0) ["year"]=> int(0) ["w"]=> int(0) ["tag"]=> string(0) "" ["cat"]=> int(16) ["tag_id"]=> string(0) "" ["author"]=> string(0) "" ["author_name"]=> string(0) "" ["feed"]=> string(0) "" ["tb"]=> string(0) "" ["paged"]=> int(0) ["meta_key"]=> string(0) "" ["meta_value"]=> string(0) "" ["preview"]=> string(0) "" ["s"]=> string(0) "" ["sentence"]=> string(0) "" ["title"]=> string(0) "" ["fields"]=> string(0) "" ["menu_order"]=> string(0) "" ["embed"]=> string(0) "" ["category__in"]=> array(0) { } ["category__not_in"]=> array(0) { } ["category__and"]=> array(0) { } ["post__in"]=> array(0) { } ["post__not_in"]=> array(0) { } ["post_name__in"]=> array(0) { } ["tag__in"]=> array(0) { } ["tag__not_in"]=> array(0) { } ["tag__and"]=> array(0) { } ["tag_slug__in"]=> array(0) { } ["tag_slug__and"]=> array(0) { } ["post_parent__in"]=> array(0) { } ["post_parent__not_in"]=> array(0) { } ["author__in"]=> array(0) { } ["author__not_in"]=> array(0) { } ["ignore_sticky_posts"]=> bool(false) ["suppress_filters"]=> bool(false) ["cache_results"]=> bool(true) ["update_post_term_cache"]=> bool(true) ["lazy_load_term_meta"]=> bool(true) ["update_post_meta_cache"]=> bool(true) ["post_type"]=> string(0) "" ["posts_per_page"]=> int(10) ["nopaging"]=> bool(false) ["comments_per_page"]=> string(2) "50" ["no_found_rows"]=> bool(false) ["order"]=> string(4) "DESC" }

Допустим, мы хотим отобразить список сообщений, принадлежащих категории «Услуги», под сообщениями, изображенными выше. Поскольку страница уже создала объект запроса для текущей категории, нам придется обойти это, манипулируя существующими основными аргументами запроса.

Давайте посмотрим, как WordPress позволяет нам достичь этого.

Функция query_posts

Функция query_posts() — это способ изменить основной запрос, который WordPress использует для отображения сообщений. Он делает это, откладывая основной запрос в сторону и заменяя его новым запросом. Вы можете убедиться в этом сами в файле wp-includes/query.php , где это представлено.

 function &query_posts($query) { unset($GLOBALS['wp_query']); $GLOBALS['wp_query'] =& new WP_Query(); return $GLOBALS['wp_query']->query($query); }

Мы попробуем добавить еще один цикл для отображения сообщений «Услуги», добавив следующие строки под endwhile; текущей стандартной петли.

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile;

И вот:

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

Попробуйте вставить var_dump ( $wp_query->query_vars["category_name"] ); после запроса Services и обновите страницу. Вы должны увидеть этот результат:

 string(8) "services"

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

Чтобы избежать этих конфликтов и выполнить очистку после вызова query_posts , сделайте вызов wp_reset_query() , и исходный основной запрос будет восстановлен. Итак, ваш код должен выглядеть так:

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; wp_reset_query(); var_dump ( $wp_query->query_vars["category_name"] );

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

 string(10) "category-1"

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

Функция get_posts()

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

Замените цикл Services, показанный ниже…

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; wp_reset_query(); var_dump ( $wp_query->query_vars["category_name"] );

…с этим:

 $my_query = get_posts( array ( 'category' => 17 ) ); foreach($my_query as $post) : setup_postdata($post); the_title( '<h4 class="example"></h4>' ); endforeach; var_dump ( $wp_query->query_vars["category_name"] );

Как видите, на этот раз нам пришлось работать с идентификатором категории вместо имени категории, в соответствии с аргументами get_posts() , определенными WordPress.

Еще одна важная вещь, на которую следует обратить внимание, это то, что хотя мы и не сбрасывали запрос, выходные var_dump категории запроса остались нетронутыми и не изменились на «сервисы». Это потому, что get_posts() сам по себе не изменяет основной запрос. Мы только что использовали новую переменную $my_query для создания нового экземпляра объекта запроса без его замены.

Функция get_posts() использует те же параметры, что и query_posts() , и рекомендуется для использования, когда вы хотите добавить статические пользовательские циклы в любом месте вашего шаблона, поскольку она безопасна и проста в использовании.

Создайте новый объект WP_Query

$wp_query является объектом класса WP_Query и извлекает необходимое содержимое базы данных для текущей страницы. Переопределение этого класса — наш способ настроить результаты и отобразить другой контент.

Это фрагмент кода, который мы будем использовать:

 $services_query = new WP_Query( 'category_name=services' ); if ( $services_query->have_posts() ) { while ( $services_query->have_posts() ) : $services_query->the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; } wp_reset_postdata(); var_dump ( $wp_query->query_vars["category_name"] );

Мы использовали аргумент «имя_категории», чтобы определить ярлык категории, в которой мы хотим, чтобы ее сообщения отображались.

Мы сохранили новый объект new WP_Query( 'category_name=services' ); в переменной $services_query .

Затем мы использовали цикл while для отображения содержимого, а после этого мы сбрасываем цикл с помощью функции wp_reset_postdata(); для восстановления исходных данных основного запроса.

Если вы хотите поэкспериментировать с другими аргументами класса WordPress WP_Query, вы можете найти полный список на его странице Кодекса WordPress.