Как выводить только родительские записи в цикле через WP_Query?
Как настроить мой пользовательский цикл, чтобы он показывал только родительские записи? У меня есть иерархический тип записи, и архивная страница отображает как родительские, так и дочерние записи.

Это решение основано на коде Джастина Тэдлока. Фильтр pre_get_posts вызывается до того, как WordPress получит записи основного цикла. В основном, вы проверяете, является ли страница архивом типа записи и убеждаетесь, что post_parent не установлен. Затем вы устанавливаете post_parent в 0, что является родителем по умолчанию для записей верхнего уровня. Проще некуда.
<?php
//Фильтр pre_get_posts вызывается до получения записей WordPress
add_filter( 'pre_get_posts', 'my_get_posts' );
function my_get_posts( $query ) {
//Если пользователь просматривает фронтенд, страница является архивом, post_parent не установлен и post_type соответствует нужному типу записи
if ( ! is_admin() && is_archive() && false == $query->query_vars['post_parent'] && $query->query_vars['post_type'] === 'my_post_type')
//Устанавливаем post_parent в 0, что является значением по умолчанию для записей верхнего уровня
$query->set( 'post_parent', 0 );
return $query;
}
?>

Развивая идею из поста @Ryan, ключевой момент - установка параметров post_parent=0
и post_type='page'
.
Вы всегда можете посмотреть SQL-запрос объекта WP_Query, чтобы понять, какие аргументы нужно добавить для получения нужных результатов.
Этот код работает у меня:
<?php
$args = array(
'post_parent' => 0, // обязательный параметр
'post_type' => 'page', // обязательный параметр
'orderby' => 'menu_order', // для отображения согласно иерархии
'order' => 'ASC', // для отображения согласно иерархии
'posts_per_page' => -1, // чтобы показать все записи (по умолчанию 10)
);
$query = new \WP_Query($args);
/* Раскомментируйте для просмотра результирующего SQL при отладке
echo $query->request; die();
//*/
if ($query->have_posts()) {
while($query->have_posts()) {
$query->the_post();
$post_id = get_the_ID();
$post = get_post($post_id, 'ARRAY_A');
echo $post['ID'] . ': ' . $post['post_title'] . '<br>';
}
}
