Аргументы WP_Query: записи, страницы и типы записей

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

Освежим память относительно работы аргументов в WP_Query

Когда вы используете WP_Query в своих темах оформления или плагинах, приходится включать в код четыре основных элемента:

  • Аргументы для запроса, в которых используются параметры, с которыми мы познакомимся в сегодняшней статье;
  • Сам запрос;
  • Цикл;
  • Завершающий этап: закрытие всех тегов if и else, а также сброс данных записи.

На практике это выглядит следующим образом:

<?php

$args = array(
    // Аргументы для вашего запроса
);

// Пользовательский запрос
$query = new WP_Query( $args );

// Проверка наличия результатов запроса
if ( $query->have_posts() ) {

    // начало цикла обработки данных из результатов запроса
    while ( $query->have_posts() ) {

        $query->the_post();

        // содержимое опрашиваемой записи

    }

}

// восстановление исходных данных записи
wp_reset_postdata();

?>

Аргументы сообщают WordPress, какие данные нужно извлекать из базы данных, и о них мы сегодня поговорим. Давайте сосредоточим внимание на самом начале кода:

$args = array(
    // Аргументы для вашего запроса
);

Как видно, аргументы заключены в массив.

Создаем код для аргументов

Есть особый способ задания аргументов в массиве:

$args = array(
    'parameter1' => 'value',
    'parameter2' => 'value',
    'parameter3' => 'value'
);

Нужно заключать параметры и их значения в одинарные кавычки, а также использовать => между ними. Аргументы и значения разделяются между собой запятыми. Если здесь что-то сделать неправильно, то WordPress может опросить не все указанные вами аргументы, или вообще ничего не выведется на экран.

Опрашиваем отдельные записи или страницы

Начнем с выполнения запроса для поиска определенной записи или страницы.

Запрос отдельной записи

Чтобы найти определенную запись (или набор схожих записей), нужно использовать два параметра:

  • p (int): по ID записи;
  • name (string): по slug записи.

Эти параметры можно использовать с любыми типами записей, включая посты, страницы, вложения и произвольные типы записей. По умолчанию, WordPress запрашивает тип записей ‘post’, и не возвращает страницы или произвольные типы записей. Если вам нужны именно они, то придется добавить больше аргументов или использовать другие.

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

$args = array(
    'p' => '32'
);

или

$args = array(
    'name' => 'post_slug'
);

Обратите внимание на то, что параметр name в качестве аргумента использует короткое имя записи, а не ее заголовок.

Параметр name позволяет определить, что ваш запрос извлечет из базы данных, когда вы в следующий раз обратитесь к коду. Но запрос не сработает, если изменить значение slug записи. ID не может быть изменено, потому этот вариант надежнее.

Запрос отдельной страницы

Чтобы осуществить запрос для отдельной страницы, используются те же два аргумента:

  • page_id (int): использует ID страницы;
  • pagename (string): использует slug страницы.

Чтобы выполнить запрос, который будет извлекать из базы данных лишь одну определенную страницу, вы можете использовать один из следующих методов:

$args = array(
    'page_id' => '20'
);

или

$args = array(
    'pagename' => 'page_slug'
);

Запрос записи другого типа

Чтобы запустить запрос записи другого типа (включая произвольные типы), нужно использовать аргумент post_type:

$args = array(
    'p' => '46',
    'post_type' => 'product'
);

Или создать запрос к вложению:

$args = array(
    'p' => '46',
    'post_type' => 'attachment'
);

Запрашиваем все дочерние страницы

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

Примечание: нельзя проделать то же самое с записями, так как они не имеют иерархии, но можно использовать этот подход к произвольному типу записей, если он имеет иерархическую структуру построения.

Есть три аргумента, которые можно использовать:

  • post_parent (int): используем ID страницы для получения только дочерних страниц. Установите этот параметр на 0, если нужно получить записи только верхнего уровня;
  • post_parent__in (array): используем массив с ID записей;
  • post_parent__not_in (array): используем массив с ID записей.

post_parent позволяет выполнять запросы к дочерним страницам.

Для поиска дочерних страниц можно использовать следующий код:

$args = array(
    'post_type' => 'page',
    'post_parent' => '2'
);

Учтите, что вам нужно будет включить аргумент post_type в качестве стандартного типа записи, в котором WP_Query будет искать записи.

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

$current_page_id = get_the_ID();

$args = array(
    'post_type' => 'page',
    'post_parent' => $current_page_id
);

Вы можете использовать этот параметр для определения страниц верхнего уровня, то есть тех, у которых отсутствуют родительские страницы:

$args = array(
    'post_type' => 'page',
    'post_parent' => '0'
);

Но что если вам нужно определить дочерние страницы нескольких страниц? Для этого нужно использовать параметр post_parent__in. Он принимает массив с ID записей.

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

$args = array(
    'post_type' => 'page',
    'post_parent__in' => array(
        '2',
        '4'
    )
);

Из запроса также возможно исключить дочерние страницы, если воспользоваться параметром post_parent__not_in:

$args = array(
    'post_type' => 'page',
    'post_parent__not_in' => array(
        '2',
        '4'
    )
);

Запросы к нескольким записям

Для включения или исключения нескольких записей можно воспользоваться двумя аргументами:

  • post__in (array): используем ID записей;
  • post__not_in (array): используем ID записей.

Аргумент post__in можно использовать для всех типов записей, и он также принимает массивы с ID. Чтобы вывести список определенных записей, можно использовать следующий код:

$args = array(
    'post__in' => array(
        '36',
        '52',
        '246',
        '354'
    )
);

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

$args = array(
    'post__in' => array(
        '36',
        '52',
        '246',
        '354'
    ),
    'ignore_sticky_posts' => 'true'
);

Аргумент post__not_in работает примерно также: принимает массив из ID записей, но при этом выводит все, за исключением перечисленных записей.

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

Чтобы сделать запрос ко всем записям типа product, но при этом исключить лишь некоторые, нужно использовать следующий код:

$args = array(
    'post_type' => 'product',
    'post__not_in' => array(
        '36',
        '52',
        '246',
        '354'
    )
);

Чтобы создать запрос ко всем страницам верхнего уровня, за исключением текущей, понадобится следующий код:

$current_page_ids = array( get_the_ID() );

$args = array(
    'post_parent' => '0',
    'post__not_in' => $current_page_ids
);

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

Делаем запрос по типам записи

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

  • post: запись;
  • page: страница;
  • revision: измененная версия;
  • attachment: вложение;
  • nav_menu_item: пункт меню навигации;
  • any: получает любой тип, за исключением измененных версий и типов с установленным значением true для параметра ‘exclude_from_search‘ при их регистрации;
  • Произвольные типы записей (например, product).

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

Пример, как сделать запрос ко всем страницам вашего сайта:

$args = array(
    'post_type' => 'page'
);

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

Делать запросы к произвольным типам записей довольно просто: используйте название типа записи, которое вы указывали при регистрации этого типа (не заголовок из панели администрирования). Предположим, вы зарегистрировали новый тип записи product при помощи register_post_type() следующим образом:

function register_product() {

    $args = array(
        'name' => __( 'Products', 'tutsplus' ),
        'singular_name' => __( 'Product', 'tutsplus' )
    );

    register_post_type( 'product', $args );
}

Значение, которое вы используете для аргумента post_type, когда делаете запрос к products, должно быть не ‘Product‘ или ‘Products‘, а ‘product‘:

$args = array(
    'post_type' => 'product'
);

Вложения

Если вы попытаетесь выполнить запрос к вложению, то у вас ничего не получится, так как WordPress устанавливает параметр вложений post_status на inherit, и настройки по умолчанию у WP_Query на ‘post_status’ => ‘publish’. Если вам нужно сделать запрос к вложениям, то в код нужно включить аргумент post_status:

$args = array(
    'post_type' => 'attachment',
    'post_status' => 'inherit'
);

Можно использовать любое значение вместо inherit.

В завершение

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

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

Существует еще много вариантов использования перечисленных аргументов. В этой статье описаны лишь их основные возможности.

Перевод статьи “WP_Query Arguments: Posts, Pages and Post Types” был подготовлен дружной командой проекта Сайтостроение от А до Я.