Cómo mostrar solo publicaciones de nivel superior en el bucle con WP_Query
¿Cómo configuro mi bucle personalizado para que solo muestre publicaciones de nivel superior? Tengo un tipo de post personalizado jerárquico y la página de archivo muestra tanto los posts padres como los hijos.

Esta solución está basada en un código de Justin Tadlock. pre_get_posts se ejecuta antes de que WordPress obtenga los posts del bucle principal. Básicamente, verificas si la página es el archivo del tipo de publicación y te aseguras de que post_parent no haya sido establecido. Luego estableces post_parent en 0, que es el padre predeterminado de los posts de nivel superior. Fácil como un pastel.
<?php
//El filtro pre_get_posts se llama antes de que WordPress obtenga los posts
add_filter( 'pre_get_posts', 'my_get_posts' );
function my_get_posts( $query ) {
//Si el usuario está viendo el frontend, la página es un archivo y post_parent no está establecido y post_type es el tipo de publicación en cuestión
if ( ! is_admin() && is_archive() && false == $query->query_vars['post_parent'] && $query->query_vars['post_type'] === 'my_post_type')
//Establece post_parent en 0, que es el post_parent predeterminado para posts de nivel superior
$query->set( 'post_parent', 0 );
return $query;
}
?>

Partiendo de la publicación de @Ryan, la clave es establecer post_parent=0
y post_type='page'
.
Siempre puedes ver la solicitud SQL del objeto WP_Query para saber qué argumentos necesitas agregar para obtener los resultados deseados.
Este código funciona para mí:
<?php
$args=array('post_parent' => 0, // requerido
'post_type' => 'page', // requerido
'orderby' => 'menu_order', // para mostrar según la jerarquía
'order' => 'ASC', // para mostrar según la jerarquía
'posts_per_page' => -1, // para mostrar todos porque el valor predeterminado es 10
);
$query = new \WP_Query( $args );
/* Descomenta para ver el SQL resultante y depurar
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>';
}
}
