Получение и вывод записей/постов WordPress - WP_Query и get_posts()
Параметры запроса постов и таксономий WordPress. Примеры фильтров и способов рендеринга постов, категорий и кастомных таксономий.
Для каждой страницы ядро WordPress формирует запрос к БД для получения записей на основе параметров GET запроса. Параметры запроса постов устанавливаются в глобальном объекте $wp_query
. При необходимости, вы можете модифицировать этот базовый запрос иди же сформировать новый объект запроса к БД - WP_Query
.
Внимание!
Не вызывайте ф-цию get_posts() и не используйте класс WP_Query непосредственно в файле functions.php! Получите мучительно долгую отладку неработающего запроса. Используйте запросы WP_Query внутри хуков или в самих шаблонах.
Внимание!
Никогда не используйте функцию query_posts()
! Эта ф-ция используется ядром WP для формирования основного запроса на получение постов по GET параметрам URL/ЧПУ. Вызвав эту ф-цию, вы замените глобальный объект основного запроса - $wp_query
. Для дополнительных кастомных запросов всегда используйте WP_Query
или обертку get_posts()
.
Если вы все же изменили глобальную переменную $wp_query
(что не рекомендуется!) с помощью функции query_posts()
, верните ее в исходное состояние с помощью wp_reset_query()
. И убедитесь, что вы делаете все правильно..
Отладка
SQL запрос объекта WP_Query хранится в свойстве request:
die($query->request);
Изменение базового запроса
Задать параметры основного/базового запроса глобальный объект запроса вы можете только через хук pre_get_posts
:
add_action('pre_get_posts', 'my_alter_category_wp_query');
function my_alter_category_wp_query(WP_Query $query) {
if (!is_category()) return;
$query->set('posts_per_page', 20);
}
Параметры GET запроса
Использование WP_Query для получения записей
Сразу приведу пример полного цикла вывода записей/постов:
<?php
// 1. Формируем параметры запроса
$args = [];
// 2. Выполняем дополнительный запрос на получение записей (похожие, последние, популярные и т.д.)
$query = new WP_Query($args);
// 3. Проверяем наличие результатов и выводим записи
if ($query->have_posts()) {
// Цикличный обход записей
while ($query->have_posts()) {
// "Извлечение" каждой последующей записи
$query->the_post();
// вывод данных каждой записи...
}
}
// 4. Восстановление данных и параметров оригинального запроса!
wp_reset_postdata();
Примечание
Ф-ция wp_reset_postdata() восстанавливает глобальную переменную $post из глобального объекта $wp_query:
$GLOBALS['wp_query']->reset_postdata();
public function reset_postdata()
{
if (!empty($this->post)) {
$GLOBALS['post'] = $this->post;
$this->setup_postdata($this->post);
}
}
Далее подробно рассмотрим детали каждого этапа и дополнительных возможностей.
Методы получения записей
Получение одной записи/поста по id или slug:
$post = get_post($postid = 14);
$query = new WP_Query(['p' => 14]); // ['name' => 'url-slug']
$query->the_post();
Примечание
Функция get_post()
- это обертка над WP_Post
, она принимает дополнительные параметры $output и $filter:
$post = get_post($postId, $output = 'OBJECT', $filter = 'raw');
$output: OBJECT, ARRAY_A, ARRAY_N
$filter: raw
Сформировать новый запрос для получения записей/постов WP_Query
:
$query_args = ['post_status' => 'publish', 'paged' => 2];
$query = new WP_Query($query_args = []);
Получение записей/постов используя функцию get_posts()
:
$posts = get_posts(['paged' => 2]);
Примечание
Функция get_posts()
- это просто обертка над WP_Query
. Принимает массив с теми же параметрами для фильтрации постов. В отличие от query_posts()
, она не вмешивается в глобальный запрос $wp_query
, а создает отдельный экземпляр класса WP_Query
. Также ф-ция get_posts()
устанавливает некоторые дефолтные значения:
$query_args = [
'post_status' => 'publish', // или inherit для attachments
'post_type' => 'post',
'numberposts' => 5, // он же posts_per_page
'category' => 0,
'orderby' => 'date',
'order' => 'DESC',
'suppress_filters' => true,
];
// ЭТИ ПАРАМЕТРЫ УСТАНАВЛИВАЮТСЯ СТАТИЧНО, БЕЗ ВОЗМОЖНОСТИ ИЗМЕНЕНИЯ
$query_args['ignore_sticky_posts'] = true;
$query_args['no_found_rows'] => true;
Фильтры записей
Основные фильтры и параметры запроса
$posts = new WP_Query([
'ignore_sticky_posts' => 'true', // не закреплять/приоритезировать записи (см. 'caller_get_posts')
'no_found_rows' => true, // отключить подсчет всех найденных записей
'post_type' => 'post', // post, page, attachment, revision, nav_menu_item, any. Default: post
'post_status' => 'publish',
'category_name' => 'reviews', // фильтр по slug
'post__in' => [1,2,3], // посты с указанными ID ('include')
'post__not_in' => [4,5], // исключить ID указанных постов ('exclude')
'meta_key' => 'some_meta_field', // сортировка по заданному meta-полю
'orderby' => 'meta_value_num', // meta_value, meta_value_num
'order' => 'ASC', // ASC, DESC
'paged' => 7, // N страницы архива ('page' - N страницы главной)
'posts_per_page' => 20, // число записей на страницу ('numberposts')
]);
Примечание
paged - Номер страницы пагинации. Показывает посты, которые в обычном режиме должны были быть показаны на странице пагинации Х. Переписывает параметр posts_per_page.
page(число) - Номер для статической домашней страницы. Показывает записи, которые в
обычном режиме должны были быть показаны на странице пагинации Х главной статической странице (front page).
Примечание
Примечание к типам постов:
attachment при получении вложения нужно установить: post_status=inherit
nav_menu_item элемент меню навигации
any все типы кроме ревизий и записей с параметром exclude_from_search=true
Фильтр по дереву (иерархии)
post_parent ID - получить дочерние страницы для указанной страницы
post_parent__in [ID] - получить дочерние для нескольких ID страниц указанных в массиве
post_parent__not_in [ID]
Фильтр по категориям
category_name 'slug,slug2' - найти записи по slug в любой из категорий
cat 'ID,-ID' - '6,7,-12' из 6 или 7 категории, но игнорировать посты из 12-ой
category__in [ID] - найти записи в любой из категорий (аналог `cat`)
category__not_in ID|[ID] - посты, которые не входят в указанные категории
category__and [ID] - найти записи, которые состоят во всех указанных категориях
Примечание
При использовании фильтра post_in
, WordPress будет
извлекать "прикрепленные" записи, даже если их ID нет в массиве! Чтобы отключить вывод "прилепленных" записей - передайте параметр ignore_sticky_posts
.
Фильтр по тегам (меткам)
tag 'SLUG,SLUG'
tag_id [ID]
tag__and [ID]
tag__in [ID]
tag__not_in [ID]
tag_slug__and [SLUG]
tag_slug__in [SLUG]
meta_query - фильтр по мета данным
Параметр meta_query представляет массив вложенных параметров фильтрации записей/постов по мета данным.
$posts = get_posts([
'relation' => 'OR', // по умолчанию AND
'meta_query' => [
[
'key' => 'название параметра',
'value' => 'значение',
'compare' => '=, !=, >, >=, <, <=, LIKE, NOT LIKE, IN, NOT IN, BETWEEN, NOT BETWEEN, EXISTS, NOT EXISTS',
'type' => 'NUMERIC, BINARY, CHAR, DATE, DATETIME, DECIMAL, SIGNED, TIME, UNSIGNED'
],
[ // только посты с изображениями
'key' => '_thumbnail_id',
'compare' => 'EXISTS' // `compare` можно опустить
],
]
]);
tax_query - фильтр по таксономиям
https://codex.wordpress.org/Class_Reference/WP_Query#Taxonomy_Parameters
Фильтр по категории кастомных постов:
$posts = get_posts([
'post_type' => 'advert',
'tax_query' => [ // (i) для одного условия фильтрации
'taxonomy' => 'advert-category',
'field' => 'slug', // 'tax_id', 'term_id', 'name', 'slug', 'term_taxonomy_id'
'terms' => 'realty', // ID, string, array
'operator' => 'NOT IN'
]
]);
Фильтр по категории и тегам:
$posts = get_posts([
'post_type' => 'advert',
'tax_query' => [
[
'taxonomy' => 'advert-category',
'field' => 'slug', // 'tax_id', 'term_id', 'name', 'slug', 'term_taxonomy_id'
'terms' => 'realty', // ID, string, array
'operator' => 'NOT IN'
], [
'taxonomy' => 'advert-tag',
'field' => 'tax_id',
'terms' => [14, 15],
'operator': 'IN'
]
]
]);
Примеры запросов
Получить дочерние страницы для текущей страницы:
$query = get_posts(['post_type' => 'page', 'post_parent' => get_the_ID()]);
Всего доступно постов:
$wp_query->found_posts;
Добавить фильтр запроса "посты только с изображениями":
add_action('pre_get_posts', 'korsun_home_get_carousel_posts_with_images_only');
function korsun_home_get_carousel_posts_with_images_only(WP_Query $query) {
if (!is_front_page()) return;
if (!in_array($query->query_vars['post_type'], ['news', 'advert'])) return;
$query->set('meta_query', [
[
'key' => '_thumbnail_id',
'compare' => 'EXISTS'
],
]);
}
Получить изображения:
$args = array(
'post_type' => 'attachment',
'post_status' => 'inherit',
'post_mime_type' => 'image/jpeg',
'fields' => 'id=>parent',
'posts_per_page' => -1,
);
Вывод записей
Цикл вывода записей
Примечание
Используйте wp_reset_postdata() для "сброса" значения глобальной переменной $post к состоянию основного запроса, после завершения любых циклов обхода записей! Поскольку каждый the_post() заменяет глобальные переменные, вы можете обнаружить, что на странице записи, например, переменная $post содержит не основной пост, а какой-то другой. Который скорее всего будет последним постом из какого-то цикла.
Дополнительные/мета поля
post_meta
Получить мета поля:
get_post_meta($post->ID, 'meta_field', $is_single_meta_field = false);
Получить ссылку на основное изображение поста:
$postImgUrl = wp_get_attachment_url(get_post_thumbnail_id($post->ID)); // вернет ссылку
$postImg = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), 'full'); // вернет массив
Array
(
[0] => http:/site.lcl/blog/wp-content/uploads/2016/03/image.png
[1] => 132
[2] => 116
[3] =>
)
WP_Query: query_vars
Получить объект (пост или таксономия) запроса для текущего маршрута/ЧПУ:
get_queried_object();
get_queried_object()->name
get_queried_object()->slug
Получить параметры запроса для текущей страницы:
$wp_query->query_vars;
Получить параметр запроса WP_Query текущей страницы (поста или записей раздела):
$cat_name = get_query_var('category_name', $default = '');
Получить объект параметров основного GET запроса текущей страницы. Параметры формируются в зависимости от страницы - это может быть набор параметров для получения поста на странице поста, или параметры получения списка постов на страницах категории/архива.
/** @var WP_Query $wp_query */
/** @var WP_Term $term */
$term = $wp_query->get_queried_object();
$term = get_queried_object(); // это просто обертка над предыдущей ф-цией
object WP_Term:
'term_id' => int 119
'name' => string 'Обзоры'
'slug' => string 'reviews'
'term_group' => int 0
'term_taxonomy_id' => int 119
'taxonomy' => string 'category'
'description' => string 'Обзоры техники и технологий'
'parent' => int 0
'count' => int 263
'filter' => string 'raw'
'cat_ID' => int 119
'category_count' => int 263
'category_description' => string 'Обзоры техники и технологий'
'cat_name' => string 'Обзоры'
'category_nicename' => string 'reviews'
'category_parent' => int 0
Пример получения название категории для архива:
get_queried_object()->name
setup_postdata($post)
Извлекает данные поста и формирует глобальные переменные поста. Использует переданную переменную $post и глобальный объект запроса $wp_query. Создаются следующие глобальные переменные: $id, $authordata, $currentday, $currentmonth, $page, $pages, $multipage, $more, $numpages.
Функция работает только при условии, что вы передаете ей глобальный объект поста с именем $post. Если у вас объект поста находится в другой переменной - установите $post = $myWpPost, после чего передайте $post в эту ф-цию. Я не очень понимаю как работает эта ф-ция, если передавать ей ID поста вместо $post.
$found_posts - количество найденных записей
$query_vars - аргументы запроса
Получение отдельных полей поста (post_type, post_title, post_status, post_content..):
$context = ''; // Фильтр значения по применению (raw, edit, db, display, attribute, js)
get_post_field($field, $post_id, $context = 'display');
См. поля $field: http://codex.wordpress.org/Database_Description#Table:_wp_posts
Источники:
- Свойства и методы WP Query (условные "теги") - https://wp-panda.com/mastering-wp_query-properties-and-methods/
- WP Query фильтр по таксономиям (taxonomy, terms) - https://wp-panda.com/wp_query-arguments-taxonomies/
#worspress, #search, #filter