Кастомизированная функция “следующий/предыдущий пост” не работает.

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

У меня есть проект, в котором есть два типа записей: “Адвокат” и “Запись” (Запись – это тип записи по умолчанию, который идет с WordPress). “Адвокат” предназначен для нашей рассылки, а “Запись” – для наших новостных бюллетеней.
Я пытаюсь сделать так, чтобы работали ссылки на следующие/предыдущие записи.
Обычно они работают только с типом записи “запись”, но я хочу, чтобы они работали с обоими типами записей “Адвокат” и “Запись”.

Я слышал, что для этого нужно переопределить часть запроса с помощью фильтра:

add_filter( "get_next_post_where", function($where, $in_same_term, $excluded_terms, $taxonomy, $post){

    //echo "<br />Старый запрос (следующий): " . $where . "<br />";
    $newWhere = str_replace(
        array( "p.post_type="advocate"", "p.post_type="post"" ),
        "(p.post_type="advocate" OR p.post_type="post")",
        $where
    );
    echo "SQLNext: " . $newWhere;
    echo "<br />";
    return $newWhere;

}, 10, 5);

add_filter( "get_previous_post_where", function($where, $in_same_term, $excluded_terms, $taxonomy, $post){

        //echo "<br />Старый запрос (предыдущий): " . $where . "<br />";
    $newWhere = str_replace(
        array( "p.post_type="advocate"", "p.post_type="post"" ),
        "(p.post_type="advocate" OR p.post_type="post")",
        $where
    );
        echo "SQLPrevious: " . $newWhere;
            echo "<br />";
    return $newWhere;

}, 10, 5);

Я добавил вывод информации, чтобы проверить, что изменяется, и убедиться, что это выглядит правильно.

Вот пример вывода для двух зарегистрированных фильтров:

SQLPrevious: WHERE p.post_date < '2024-04-14 11:00:00' AND (p.post_type="advocate" OR (p.post_type="advocate" OR p.post_type="post")) AND ( p.post_status="publish" OR p.post_status="private" )

SQLNext: WHERE p.post_date > '2024-04-14 11:00:00' AND (p.post_type="advocate" OR (p.post_type="advocate" OR p.post_type="post")) AND ( p.post_status="publish" OR p.post_status="private" )

введите описание изображения здесь

Изображение выше взято со страницы facetWP, которая возвращает как адвокатов, так и записи. Второй элемент – это Адвокат, а остальные – это обычные записи (бюллетени).
Если вы посмотрите на адвоката внизу, он показывает следующие и предыдущие бюллетени (тип записи “запись”), как и должно быть, но если вы перейдете к статье “Сообщество Ла Орожи выигрывает выдающееся судебное решение”, следующей статьей должна быть “Тестовый адвокат”, но она пропускается и идет сразу к “Местные голоса на Всемирном конгрессе рыбного хозяйства”.
Кажется, что если смотреть на бюллетень, система просто не видит адвокатов.

Чтобы получить навигацию по предыдущим/следующим записям в файле single-advocate.php, я вывожу эту функцию внизу страницы:

echo blocksy_post_navigation();

blocksy_post_navigation – это функция, которая идет с темой Blocksy, и вместо того, чтобы просто создавать ссылки на предыдущие/следующие записи, она создает симпатичные ссылки с изображениями.

/**
 * Вывод навигации по записям.
 */
if (! function_exists('blocksy_post_navigation')) {
function blocksy_post_navigation() {
    $prefix = blocksy_manager()->screen->get_prefix();

    $next_post = apply_filters(
        'blocksy:post-navigation:next-post',
        get_adjacent_post(false, '', true)
    );

    $previous_post = apply_filters(
        'blocksy:post-navigation:previous-post',
        get_adjacent_post(false, '', false)
    );

    $post_nav_criteria = blocksy_get_theme_mod($prefix . '_post_nav_criteria', 'default');

    if ($post_nav_criteria !== 'default') {
        $post_type = get_post_type();
        $post_nav_taxonomy_default = array_keys(blocksy_get_taxonomies_for_cpt(
            $post_type
        ))[0];

        $post_nav_taxonomy = blocksy_get_theme_mod(
            $prefix . '_post_nav_taxonomy',
            $post_nav_taxonomy_default
        );

        $next_post = apply_filters(
            'blocksy:post-navigation:next-post',
            get_adjacent_post(true, '', true, $post_nav_taxonomy)
        );

        $previous_post = apply_filters(
            'blocksy:post-navigation:previous-post',
            get_adjacent_post(true, '', false, $post_nav_taxonomy)
        );
    }

    if (! $next_post && ! $previous_post) {
        return '';
    }

    $title_class="item-title";

    $title_class .= ' ' . blocksy_visibility_classes(blocksy_get_theme_mod(
        $prefix . '_post_nav_title_visibility',
        [
            'desktop' => true,
            'tablet' => true,
            'mobile' => false,
        ]
    ));

    $thumb_size = blocksy_get_theme_mod($prefix . '_post_nav_thumb_size', 'medium');

    $thumb_class="";

    $thumb_class .= ' ' . blocksy_visibility_classes(blocksy_get_theme_mod(
        $prefix . '_post_nav_thumb_visibility',
        [
            'desktop' => true,
            'tablet' => true,
            'mobile' => true,
        ]
    ));

    $container_class="post-navigation ct-constrained-width";

    $container_class .= ' ' . blocksy_visibility_classes(blocksy_get_theme_mod(
        $prefix . '_post_nav_visibility',
        [
            'desktop' => true,
            'tablet' => true,
            'mobile' => true,
        ]
    ));

    $home_page_url = get_home_url();

    $post_slug = get_post_type_object(get_post_type())->labels->singular_name;
    $post_slug = '<span>' . $post_slug . '</span>';

    $next_post_image_output="";
    $previous_post_image_output="";

    if ($next_post) {
        $next_title="";

        $next_title = $next_post->post_title;

        if (get_post_thumbnail_id($next_post)) {
            $next_post_image_output = blocksy_media(
                [
                    'attachment_id' => get_post_thumbnail_id($next_post),
                    'post_id' => $next_post->ID,
                    'ratio' => '1/1',
                    'size' => $thumb_size,
                    'class' => $thumb_class,
                    'inner_content' => '<svg width="20px" height="15px" viewBox="0 0 20 15" fill="#ffffff"><polygon points="0,7.5 5.5,13 6.4,12.1 2.4,8.1 20,8.1 20,6.9 2.4,6.9 6.4,2.9 5.5,2 "/></svg>',
                    'tag_name' => 'figure'
                ]
            );
        }
    }

    if ($previous_post) {
        $previous_title="";

        $previous_title = $previous_post->post_title;

        if (get_post_thumbnail_id($previous_post)) {
            $previous_post_image_output = blocksy_media(
                [
                    'attachment_id' => get_post_thumbnail_id($previous_post),
                    'post_id' => $previous_post->ID,
                    'ratio' => '1/1',
                    'size' => $thumb_size,
                    'class' => $thumb_class,
                    'inner_content' => '<svg width="20px" height="15px" viewBox="0 0 20 15" fill="#ffffff"><polygon points="14.5,2 13.6,2.9 17.6,6.9 0,6.9 0,8.1 17.6,8.1 13.6,12.1 14.5,13 20,7.5 "/></svg>',
                    'tag_name' => 'figure'
                ]
            );
        }
    }

    $prefix = blocksy_manager()->screen->get_prefix();

    $deep_link_args = [
        'prefix' => $prefix,
        'suffix' => $prefix . '_has_post_nav'
    ];

    ob_start();

    ?>

        <nav class="<?php echo esc_attr( $container_class ); ?>" <?php echo blocksy_generic_get_deep_link($deep_link_args); ?>>
            <?php if ($next_post) { ?>
                <a href="<?php echo esc_url(get_permalink($next_post)); ?>" class="nav-item-prev">
                    <?php
                        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                        echo $next_post_image_output;
                    ?>

                    <div class="item-content">
                        <span class="item-label">
                            <?php
                                echo wp_kses_post(blocksy_safe_sprintf(
                                    apply_filters(
                                        'blocksy:post-navigation:previous-post:label',
                                        // translators: post title
                                        //__('Предыдущий %s', 'blocksy')
                                        __('Предыдущая запись', 'blocksy')
                                    ),
                                    $post_slug
                                ));
                            ?>
                        </span>

                        <?php if ( ! empty( $next_title ) ) { ?>
                            <span class="<?php echo esc_attr( $title_class ); ?>">
                                <?php echo wp_kses_post($next_title); ?>
                            </span>
                        <?php } ?>
                    </div>

                </a>
            <?php } else { ?>
                <div class="nav-item-prev"></div>
            <?php } ?>

            <?php if ($previous_post) { ?>
                <a href="<?php echo esc_url(get_permalink($previous_post)); ?>" class="nav-item-next">
                    <div class="item-content">
                        <span class="item-label">
                            <?php
                                echo wp_kses_post(blocksy_safe_sprintf(
                                    apply_filters(
                                        'blocksy:post-navigation:next-post:label',
                                        // translators: post title
                                        //__('Следующий %s', 'blocksy')
                                        __('Следующая запись', 'blocksy')
                                    ),
                                    $post_slug
                                ));
                            ?>
                        </span>

                        <?php if ( ! empty( $previous_title ) ) { ?>
                            <span class="<?php echo esc_attr( $title_class ); ?>">
                                <?php echo wp_kses_post($previous_title); ?>
                            </span>
                        <?php } ?>
                    </div>

                    <?php
                        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                        echo $previous_post_image_output;
                    ?>
                </a>
            <?php } else { ?>
                <div class="nav-item-next"></div>
            <?php } ?>

        </nav>

    <?php

    return ob_get_clean();
}
}

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

Любая помощь в том, как включить моего адвоката, когда система создает ссылки на предыдущие/следующие записи, будет очень ценна.

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

Проблема, с которой вы столкнулись при настройке навигации между записями в WordPress для нескольких типов записей, таких как "Advocate" и "Post", часто возникает из-за особенности работы функции get_adjacent_post(). Эта функция по умолчанию фильтрует записи только по одному типу, что может привести к нежелательным результатам в вашей навигации.

Анализ проблемы

На основании описанного вами кода, необходимость кастомизации фильтра get_next_post_where и get_previous_post_where очевидна. Вы уже правильно используете str_replace для модификации SQL-запроса, однако есть несколько моментов, которые стоит проверить и улучшить.

Пример исправленного кода

Обратите внимание, что дублирование условий, как, например в вашем случае с p.post_type="advocate" в строке условия, может создавать неэффективные запросы. Вместо этого можно использовать конструкцию, которая более четко формулирует запрос:

add_filter("get_next_post_where", function($where, $in_same_term, $excluded_terms, $taxonomy, $post){
    $newWhere = str_replace(
        array('p.post_type="advocate"', 'p.post_type="post"'),
        '(p.post_type="advocate" OR p.post_type="post")',
        $where
    );
    return $newWhere;
}, 10, 5);

add_filter("get_previous_post_where", function($where, $in_same_term, $excluded_terms, $taxonomy, $post){
    $newWhere = str_replace(
        array('p.post_type="advocate"', 'p.post_type="post"'),
        '(p.post_type="advocate" OR p.post_type="post")',
        $where
    );
    return $newWhere;
}, 10, 5);

Рекомендации по отладке

  1. Логи SQL-запросов: Поскольку вы уже добавили вывод SQL-запросов, убедитесь, что они корректны и что измененное условие действительно включается в запрос. Особенно внимательно следите за тем, как формируется финальное SQL-выражение.

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

  3. Использование функции get_adjacent_post: Убедитесь, что параметры этой функции вызываются правильно в blocksy_post_navigation(). Вы можете попробовать передать false в качестве третьего аргумента, чтобы убрать фильтрацию по терминам таксономии, что может улучшить ситуацию.

Заключение

Если после внесённых изменений проблема остается актуальной, стоит рассмотреть возможность использования функции wp_get_recent_posts() для получения списка записей обоих типов и реализации навигации на основе этого списка. Такой подход позволит избежать потенциальных проблем с запросами SQL и наладить работу навигации.

Также рекомендуется протестировать обновленные функции в локальной среде или на тестовом сервере, прежде чем применять изменения на рабочем сайте. Это даст вам возможность удостовериться в правильности работы всех компонентов.

Если потребуется дополнительная помощь, не стесняйтесь задавать вопросы. Удачи в доработке вашей функциональности WordPress!

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

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