Отображение публикаций исключительно в их категории (не родительской)

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

Я использую пользовательский тип записи для добавления/отображения PDF-документов (записей) на своем сайте.

таксономия – wpl_documents_category

тип записи – post_documents

Все работает хорошо. Однако я хочу отображать записи исключительно в их категории – будь то родительская или дочерняя категория.

Пример ниже

Иерархия: Родительская категория -> Дочерняя категория 1 -> Дочерняя категория 2

Название записи: Пример Документа

Категория записи: Дочерняя категория 2

По умолчанию WordPress будет показывать эту запись на всех 3 уровнях. Однако я хочу, чтобы она отображалась только в категории, к которой она принадлежит (Дочерняя категория 2) только.

Запрос ниже

<?php if ( $wp_query->have_posts() ) : while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>

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

Любые идеи/информация по вышеуказанному будут очень признательны!

ИЗМЕНЕНИЕ

Полный запрос

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php
$pid = $post->ID;
$document_file = get_post_meta( $pid, 'wpl_document_file', true);
$document_file_size = get_post_meta( $pid, 'wpl_document_file_size', true);
$document_authors = get_post_meta( $pid, 'wpl_document_authors', true);
?>

HTML-разметка идет здесь с вызовами для вывода вышеуказанной информации

Отображаемые категории

<?php $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) ); if ($term->parent == 0) { ?>
<?php wp_list_categories('taxonomy=wpl_documents_category&depth=1&title_li=&child_of=" . $term->term_id); ?>

Вот мой полный archive-post_documents.php

<?php
/**
 * Шаблон по умолчанию для отображения архива документов
 *
 * @package WordPress
 */
?>

<?php get_header(); ?>
<div id="main" class="site-main container_12">
    <div id="primary" class="content-area ms grid_12"> 
        <div id="content" class="site-content">    
            <?php if (category_description( $category ) == '') { ?>
            <?php } else { ?>
            <article class="single">
                <div id="subcats" class="entry-content">          
                    <h2>Описание</h2>
                    <?php echo category_description( $category_id ); ?>
                </div> 
            </article> 
            <?php } ?>             
            <?php
                $term = get_queried_object();
                $children = get_terms( $term->taxonomy, array(
                'parent'    => $term->term_id,
                'hide_empty' => 0,
                'show_count' => 0
                ) );
            if($children) {
            ?>
            <article class="single">
                <div id="subcats" class="entry-content">             
                    <?php 
                    $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) ); 
                    if ($term->parent == 0) { ?>
                    <h2>Просмотр подкатегорий:</h2> 
                    <ul>
                        <?php wp_list_categories('taxonomy=wpl_documents_category&depth=1&title_li=&child_of=" . $term->term_id); ?>
                    </ul>   
                        <?php } else { ?>
                    <h2>Просмотр подкатегорий:</h2> 
                    <ul>
                        <?php wp_list_categories("taxonomy=wpl_documents_category&&title_li=&child_of=" . $term->term_id); } ?>
                    </ul>     
                </div> 
            </article> 
            <?php } ?>             
            <div>&nbsp;</div>
        </div>    

        <div id="content" class="site-content js-masonry">
            <?php if ( have_posts() ) : ?>
            <?php while ( have_posts() ) : the_post(); ?>
            <?php //if ( $wp_query->have_posts() ) : while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
                <?php
                    $pid = $post->ID;
                    $document_file = get_post_meta( $pid, 'wpl_document_file', true);
                    $document_file_size = get_post_meta( $pid, 'wpl_document_file_size', true);
                    $document_authors = get_post_meta( $pid, 'wpl_document_authors', true);
                    $icon = wplook_get_icon_name($document_file);
                ?>

                    <article id="post-<?php the_ID(); ?>" <?php post_class('item'); ?>>
                        <?php if ( has_post_thumbnail() ) {?> 
                            <figure>
                                <a title="<?php the_title();?>" href="<?php echo $document_file; ?>" download="<?php preg_replace("/[^a-zA-Z0-9_-]/", "", the_title);?>">
                                    <?php the_post_thumbnail('document-image'); ?>
                                </a>
                            </figure>
                        <?php } else {?> 
                            <figure>
                                <a title="<?php the_title();?>" href="<?php echo $document_file; ?>" download="<?php preg_replace("/[^a-zA-Z0-9_-]/", "", the_title);?>">
                                    <img data-lazy-loaded="true" style="display: block;" src="http://www.absa.asn.au/absainc/wp-content/uploads/2014/09/pdficon-260x173.jpg" class="attachment-document-image wp-post-image" alt="pdficon" height="173" width="260">
                                </a>
                            </figure>
                        <?php } ?>

                        <div class="box-conten-margins">
                            <h1 class="entry-header">
                                <a title="<?php the_title(); ?>" href="<?php echo $document_file; ?>" download="<?php preg_replace("/[^a-zA-Z0-9_-]/", "", the_title);?>"><?php the_title(); ?></a>
                            </h1>

                            <div class="short-description">
                                <p><i class="<?php echo $icon; ?>"></i> <strong>Размер:</strong> <span class="filesize"><?php echo $document_file_size; ?></span></p>
                                <?php if ($document_authors) { ?>
                                <p><strong>Автор(ы):</strong> <?php echo $document_authors; ?></p>
                                <?php } ?>
                            </div>

                            <div class="clear"></div>

                            <div class="entry-meta">
                                <a class="buttonsx" href="<?php echo $document_file; ?>" download="<?php preg_replace("/[^a-zA-Z0-9_-]/", "", the_title);?>"><i class="<?php echo $icon; ?>"></i> <?php _e('Скачать PDF', 'wplook'); ?></a>
                                <div class="clear"></div>
                            </div>

                        </div>
                    </article>

            <?php endwhile; wp_reset_postdata(); ?>
            <?php else : ?>
                <p><?php _e('Извините, нет документов для отображения. Это может быть связано с тем, что вы не являетесь членом ABSA или с тем, что в этой категории просто нет документов.', 'wplook'); ?></p>
            <?php endif; ?>

        </div>
        <div class="pagination-grid">
            <?php wplook_content_navigation('postnav' ) ?>
        </div>
    </div>

    <div class="clear"></div>

</div><!-- #main .site-main -->
<?php get_footer(); ?>

Вот интересный подход к этому

КОНЦЕПЦИЯ

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

ПРОБЛЕМЫ С ВАШИМ ТЕКУЩИМ КОДОМ

Так как это всего лишь страница архива, которая не используется как страница таксономии, у вас есть несколько серьезных ошибок. Следующий код

<div id="content" class="site-content">    
    <?php if (category_description( $category ) == '') { ?>
    <?php } else { ?>
    <article class="single">
        <div id="subcats" class="entry-content">          
            <h2>Описание</h2>
            <?php echo category_description( $category_id ); ?>
        </div> 
    </article> 
    <?php } ?>             
    <?php
        $term = get_queried_object();
        $children = get_terms( $term->taxonomy, array(
        'parent'    => $term->term_id,
        'hide_empty' => 0,
        'show_count' => 0
        ) );
    if($children) {
    ?>
    <article class="single">
        <div id="subcats" class="entry-content">             
            <?php 
            $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) ); 
            if ($term->parent == 0) { ?>
            <h2>Просмотр подкатегорий:</h2> 
            <ul>
                <?php wp_list_categories('taxonomy=wpl_documents_category&depth=1&title_li=&child_of=" . $term->term_id); ?>
            </ul>   
                <?php } else { ?>
            <h2>Просмотр подкатегорий:</h2> 
            <ul>
                <?php wp_list_categories("taxonomy=wpl_documents_category&&title_li=&child_of=" . $term->term_id); } ?>
            </ul>     
        </div> 
    </article> 
    <?php } ?>             
    <div>&nbsp;</div>
</div>  

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

РАБОЧИЙ ПРОЦЕСС

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

Что нам нужно сделать, так это получить список всех записей для конкретного типа записи в архиве, специфичном для таксономии. Это будет сделано с помощью tax_query с WP_Query. get_terms() будет использована для получения списка терминов, которые принадлежат указанной таксономии. Это будет использовано в tax_query для получения записей.

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

Когда все записи будут возвращены, нам нужно получить термины, к которым принадлежит каждая запись. Для этого мы используем get_the_terms()

Чтобы предусмотреть записи, которые принадлежат родительскому и/или дочернему и/или внуковому термину, я отсортировал возвращаемый массив терминов с помощью usort по ID термина, чтобы последний в строке термин появлялся первым. Этот термин будет внуковым или дочерним.

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

Первый термин в отсортированном массиве будет использоваться для создания этого списка и добавления заголовка записи под ним.

Этот новый массив, который создается, будет отсортирован с помощью ksort, чтобы список терминов сортировался в алфавитном порядке. Записи сортируются по дате записи.

Я также добавил временный элемент, чтобы сделать функцию более быстрой и менее ресурсоемкой. Этот список будет обновляться каждые 24 часа, вы можете просто изменить это по мере необходимости, сделать его длиннее. Выберите продолжительность времени, которая соответствует тому, как часто вы добавляете новые записи. Если вы добавляете новые записи еженедельно, установите время истечения временного элемента раз в неделю.

Чтобы убедиться, что список обновляется всякий раз, когда запись удаляется, публикуется или обновляется, используется действие transition_post_status для удаления временного элемента всякий раз, когда запись публикуется, удаляется или обновляется.

ДАВАЙТЕ КОДИРОВАТЬ

Вот код, вставьте это все в ваш functions.php

function get_term_post_list( $taxonomy = "category', $post_type="post" ) {

    if ( false === ( $q = get_transient( 'term_list' ) ) ) {

        $q = '';

        $term_ids = get_terms( $taxonomy, 'fields=ids' );
        if ( ! empty( $term_ids ) && ! is_wp_error( $term_ids ) ){

            $args = array( 
                'posts_per_page' => -1,
                'post_type' => $post_type,
                'fields' => 'names',
                'tax_query' => array(
                    array(
                        'taxonomy' => $taxonomy,
                        'field'    => 'term_id',
                        'terms'    => $term_ids,
                    ),
                ),
            );

            $query = new WP_Query($args); 
            ?><   
            if( $query->have_posts() ) {

                while ( $query->have_posts() ) { 

                    $query->the_post(); 

                    $a="<a href="". get_permalink() .'">' . get_the_title() .'</a>';

                    $all_terms = get_the_terms( $query->post->ID, $taxonomy );
                    $terms = array_values( $all_terms );        

                    usort( $terms, function ( $a, $b ) {
                        return ($a->term_id < $b->term_id) ? 1 : -1;
                    });

                    $b = ucfirst( $terms[0]->name );    

                    $q[$b][] = $a; // Создать массив с именами категорий и заголовками записей
                }

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

            }

            ksort( $q );
        }

        set_transient( 'term_list', $q, 24 * HOUR_IN_SECONDS );
    }
    return $q;
}

add_action( 'transition_post_status', function ( $new_status, $old_status, $post )
{

    delete_transient( 'term_list' );

}, 10, 3 );

КАК ИСПОЛЬЗОВАТЬ

Вот как код будет использоваться в вашем шаблонном файле, archive-post_documents.php

$lists = get_term_post_list( $taxonomy = 'wpl_documents_category', $post_type="post_documents"  );
foreach ($lists as $key=>$values) {

    echo $key;

    echo '<ul>';
        foreach ($values as $value){
            echo '<li>' . $value . '</li>';
        }
    echo '</ul>';
}

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

Отображение постов исключительно в их категории (без родительской)

Работая с кастомными типами постов в WordPress, вы можете столкнуться с ситуацией, когда необходимо выводить посты только в их конкретной категории, игнорируя родительские и другие уровни иерархии. В вашем случае, это касается кастомного типа постов для PDF-документов, который использует таксономию wpl_documents_category. Этот подход позволит вам обойти стандартное поведение WordPress, и отобразить посты только в той категории, к которой они принадлежат.

Проблема

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

Решение

Для достижения этой цели мы можем использовать кастомный WP_Query с параметрами tax_query, а также функцию для сортировки терминов в порядке их ID, чтобы гарантировать, что отображается только самая нижняя категория (т.е. наименьшая иерархическая категория).

Вот шаги, которые необходимо предпринять:

1. Создание функции для получения и отображения постов:

Создайте следующую функцию в файле functions.php вашей темы:

function get_term_post_list( $taxonomy = "wpl_documents_category", $post_type = "post_documents" ) {
    if ( false === ( $q = get_transient( 'term_list' ) ) ) {
        $q = array();

        // Получаем все термины таксономии
        $term_ids = get_terms( $taxonomy, 'fields=ids' );
        if ( ! empty( $term_ids ) && ! is_wp_error( $term_ids ) ) {
            $args = array(
                'posts_per_page' => -1,
                'post_type' => $post_type,
                'tax_query' => array(
                    array(
                        'taxonomy' => $taxonomy,
                        'field'    => 'term_id',
                        'terms'    => $term_ids,
                    ),
                ),
            );

            $query = new WP_Query($args);
            if( $query->have_posts() ) {
                while ( $query->have_posts() ) {
                    $query->the_post();

                    // Получаем термины поста
                    $terms = get_the_terms( get_the_ID(), $taxonomy );
                    if ($terms) {
                        usort($terms, function($a, $b) {
                            return $a->term_id <=> $b->term_id;
                        });

                        // Используем самую нижнюю категорию
                        $lowest_term = $terms[0]->name;
                        $link = '<a href="'.get_permalink().'">'.get_the_title().'</a>';
                        $q[$lowest_term][] = $link;
                    }
                }

                wp_reset_postdata();
            }

            ksort($q);
        }

        set_transient( 'term_list', $q, 24 * HOUR_IN_SECONDS );
    }
    return $q;
}

2. Удаление транзиентов при обновлении поста:

add_action('transition_post_status', function($new_status, $old_status, $post){
    delete_transient('term_list');
}, 10, 3);

3. Использование функции в archive-post_documents.php:

Теперь, когда функция готова, вы можете легко её использовать в вашем шаблоне для архитектуры archive-post_documents.php:

$lists = get_term_post_list();
foreach ($lists as $term => $posts) {
    echo '<h2>' . esc_html($term) . '</h2>';
    echo '<ul>';
    foreach ($posts as $post) {
        echo '<li>' . $post . '</li>';
    }
    echo '</ul>';
}

Заключение

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

SEO Оптимизация

Используя правильные заголовки и структуры ссылок с помощью функции get_permalink(), вы также усилите SEO-оптимизацию вашего контента, что сделает его более доступным для поисковых систем.

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

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