WP_Query: комбинация “post_parent” и “post_type” возвращает странные результаты

Вопрос или проблема

Я получаю интересные результаты, используя post_parent вместе с post_type (локально, WP 5.8):

У меня есть пользовательский тип записи project'hierarchical' => true), где я получаю все дочерние записи родителя на одном представлении с помощью WP_Query.

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

Если я устанавливаю post_type на any, тогда я получаю правильные дочерние записи. Я уже проверил, чтобы убедиться, что $post->ID для родителя корректен (и не 0) и что записи все имеют один и тот же пользовательский тип записи. Я также дважды проверил базу данных на странности и подтвердил взаимосвязи родитель-дитя.

Чтобы сделать это еще страннее, это происходит на моем локальном компьютере; предыдущий код (устанавливающий post_parent И post_type) работает нормально на живом/производственном сайте (хотя он на более ранней версии WP).

Вот запрос:

$args = array(
    'post_type'   => 'project',
    'post_status' => 'publish',
    'post_parent' => $post->ID,
    'posts_per_page' => -1,
    'orderby' => 'menu_order title',
    'order' => 'ASC'
);

$projects = new WP_Query( $args );
if( $projects->have_posts() ) :
    while( $projects->have_posts() ) :
        $projects->the_post();

Как описано, если я изменяю на 'post_type' => 'any',, тогда я получаю правильные дочерние записи.

Что я упускаю? Порчен ли мои данные (хотя я не вижу никаких доказательств этого)…

Оказалось, у меня есть ошибочная функция pre_get_posts:

function fgw_parents_only( $query ) {
    if ( ! is_admin() && $query->is_post_type_archive( 'project' ) ) {
        $query->set( 'post_parent', 0 );
        $query->set( 'posts_per_page', -1);
    }
}
add_action( 'pre_get_posts', 'fgw_parents_only' );

Не совсем уверен, почему is_post_type_archive вызвало это на шаблоне single-project.php, но я смог решить это, изменив условие на:

if ( ! is_admin() && $query->is_post_type_archive( 'project' ) && ! is_single() ) {

.

Ответ или решение

WP_Query: Проблемы с "post_parent" и "post_type"

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

1. Суть проблемы

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

$args = array(
    'post_type'   => 'project',
    'post_status' => 'publish',
    'post_parent' => $post->ID,
    'posts_per_page' => -1,
    'orderby' => 'menu_order title',
    'order' => 'ASC'
);

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

2. Причина проблемы

Ваше решение для WP_Query сталкивается с конфликтом, вызванным функцией pre_get_posts, которую вы добавили в код:

function fgw_parents_only( $query ) {
    if ( ! is_admin() && $query->is_post_type_archive( 'project' ) ) {
        $query->set( 'post_parent', 0 );
        $query->set( 'posts_per_page', -1);
    }
}
add_action( 'pre_get_posts', 'fgw_parents_only' );

Этот фильтр влияет на запросы к вашим постам типа project. is_post_type_archive вызывается во многих контекстах, не только в архиве. Ваша проверка предполагает, что функция будет активна только на страницах архивов, однако, она также может срабатывать на страницах отдельных записей. Поэтому, когда вы запрашиваете дочерние записи, фильтр может преобразовывать ваш запрос, устанавливая post_parent в 0.

3. Решение проблемы

Как вы уже заметили, исправление проверки на is_single() решает вашу проблему. Вот корректированный код:

if ( ! is_admin() && $query->is_post_type_archive( 'project' ) && ! is_single() ) {

Это изменение гарантирует, что фильтр pre_get_posts применяется только к архивам, а не к отдельным записям, тем самым предоставляя правильные результаты вашего запроса.

Заключение

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

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

Оцените материал
Добавить комментарий

Капча загружается...