it-swarm.com.ru

Сортировка списка сообщений, отображаемых под списком связанных терминов (которые должны быть отсортированы без первоначальных статей)

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

Сортировка списка сообщений CPT, перечисленных в соответствующих пользовательских условиях таксономии

Я нашел этот фрагмент кода в ответ на этот вопрос , который идеально подходит для возврата списка всех пользовательских терминов таксономии со списком связанных пользовательских типов записей под каждым.

$custom_terms = get_terms('custom_taxonomy');

foreach($custom_terms as $custom_term) {
    wp_reset_query();
    $args = array('post_type' => 'custom_post_type',
        'tax_query' => array(
            array(
                'taxonomy' => 'custom_taxonomy',
                'field' => 'slug',
                'terms' => $custom_term->slug,
            ),
        ),
     );

     $loop = new WP_Query($args);
     if($loop->have_posts()) {
        echo '<h2>'.$custom_term->name.'</h2>';

        while($loop->have_posts()) : $loop->the_post();
            echo '<a href="'.get_permalink().'">'.get_the_title().'</a>';
        endwhile;
     }
}

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

Обычно я просто добавляю 'orderby' => 'title' где-то в миксе, но здесь это не работает, или я не могу понять, где его следует добавить.

Кто-нибудь знает, как их отсортировать?

ОБНОВИТЬ

Попытка добавления 'orderby' => 'title' после 'post_type' => 'custom_post_type' в $args, которая не имела никакого эффекта.

Игнорирование исходной статьи "The" из пользовательских условий таксономии вернулось

С помощью некоторого кода из эта запись в блоге и эти исправления и предложения по улучшению Мне удалось получить список всех сообщений в пользовательском типе сообщения и отобразить их в алфавитном порядке, игнорируя "The" в заголовках сообщений.

Теперь я также хотел бы, чтобы мой список пользовательских терминов таксономии возвращался аналогичным образом, если это вообще возможно.

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

function wpcf_create_temp_column($fields) {
  global $wpdb;
  $matches = 'The';
  $has_the = " CASE 
      WHEN $wpdb->posts.post_title regexp( '^($matches)[[:space:]]' )
        THEN trim(substr($wpdb->posts.post_title from 4)) 
      ELSE $wpdb->posts.post_title 
        END AS title2";
  if ($has_the) {
    $fields .= ( preg_match( '/^(\s+)?,/', $has_the ) ) ? $has_the : ", $has_the";
  }
  return $fields;
}

function wpcf_sort_by_temp_column ($orderby) {
  $custom_orderby = " UPPER(title2) ASC";
  if ($custom_orderby) {
    $orderby = $custom_orderby;
  }
  return $orderby;
}

Это позволяет мне использовать этот фильтр с помощью параметра _custom orderby:

add_filter( 'posts_orderby', function( $orderby, \WP_Query $q )
{
    // Do nothing
    if( '_custom' !== $q->get( 'orderby' ) )
        return $orderby;

    global $wpdb;

    $matches = 'The';   // REGEXP is not case sensitive here

    // Custom ordering (SQL)
    return sprintf( 
        " 
        CASE 
            WHEN {$wpdb->posts}.post_title REGEXP( '^($matches)[[:space:]]+' )
                THEN TRIM( SUBSTR( {$wpdb->posts}.post_title FROM %d )) 
            ELSE {$wpdb->posts}.post_title 
        END %s
        ",
        strlen( $matches ) + 1,
        'ASC' === strtoupper( $q->get( 'order' ) ) ? 'ASC' : 'DESC'     
    );

}, 10, 2 );

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

Можно ли переписать код, чтобы применить его к терминам таксономии в списке, а не в публикациях?

Ограничение списка возвращаемых терминов таксономии + связанных сообщений теми, которые начинаются с определенной буквы

На данный момент список терминов таксономии + соответствующие сообщения вернулся очень длинный. Чтобы сделать его немного более управляемым при просмотре списка, я хотел бы разбить его на 5 или 6 страниц, отображая термины в алфавитном порядке от A-E, F-J и т.д.

Если это не выполнимо, я бы хорошо разделил его на А, В, С, D и т.д.

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

ОБНОВИТЬ

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

$game_titles = get_terms('game');
$count = count($game_titles);
$letters = 'A';
if($count > 0){

foreach($game_titles as $game_title) {
    wp_reset_query();
    $args = array('post_type' => 'release',
        'tax_query' => array(
            array(
                'taxonomy' => 'game',
                'field' => 'slug',
                'terms' => $game_title->slug,
            ),
        ),
    );
    unset($game_titles);

    if (preg_match("/^$letters/i", $term->name)){
    $loop = new WP_Query($args);
    if($loop->have_posts()) {
        echo '<h2>' . $game_title->name . '</h2>';
        echo '<ul>';
        unset($game_title);
        unset($args);

        while($loop->have_posts()) : $loop->the_post();
        /* code */

        endwhile;
        echo '</ul>';
    }
    }
}
}

ОБНОВЛЕНИЕ - Добавлен код PieterGoosen

Я добавил код из ответа @ PieterGoosen, приведенного ниже, в мой functions.php (код идентичен указанному в ответе) и файл шаблона страницы ( код с добавленным содержимым цикла можно увидеть здесь ).

То, что я получаю, отчасти верно, но есть некоторые вещи не так. С новым кодом я получаю список всех сообщений CPT release, отсортированных по 1 связанному термину game. Выбранный термин - это термин, начинающийся с самой ранней встречающейся буквы в алфавите - как в астероидах будет выбран вместо Pac-Man, но Pac-Man будет выбран над Space Invaders.

Он должен отображать список всех терминов game и под каждым термином список всех связанных сообщений release. Более того, похоже, что каждый пост release отображается только один раз, хотя в оптимальном варианте я хотел бы, чтобы они появлялись снова под каждым термином game, если с ними связано более одного.

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

ОБНОВЛЕНИЕ 2 - Тестирование нового кода PieterGoosen

Я обновил свой код с обновленным кодом, и он работает как шарм. Все, что мне нужно сделать, это применить стилизацию и зациклить содержимое.

Для справки, это решение ДЕЙСТВИТЕЛЬНО улучшило количество запросов к базе данных на моей странице по сравнению с моим старым кодом (как видно в верхней части этого вопроса. Использование get_num_queries() для проверки - мой старый код имел 3166 запросов к базе данных. С новым кодом я вместо 33 (+ теперь я на самом деле получаю все данные, которые я хочу отобразить + страница загружается быстрее).

2
rpbtz

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

PRELUDE

Весь мой код в этом вопросе основан на следующем типе поста и таксономии, поэтому, прежде чем запускать какой-либо код, обязательно настройте тип поста и таксономию в соответствии с вашими требованиями.

  • Пользовательский тип записи ->release

  • Пользовательская таксономия ->game

ВАЖНОЕ ОБНОВЛЕНИЕ

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

Новое решение идеально подойдет решение от @birgire к вашему предыдущему вопросу так как мы теперь сортируем сам запрос, а не возвращаемые посты.

Мое первоначальное решение того же вопроса, который вы задали для этого больше не нужны для решения этой проблемы, так что вам решать, хотите ли вы по-прежнему создавать и сортировать цикл со скрытым пользовательским поле. Мое решение, использующее настраиваемое поле, все еще полностью верно. Поскольку мой первоначальный ответ на этот вопрос включал мое решение для настраиваемого поля, я буду продолжать его использовать, хотя я постараюсь показать изменения, которые вы можете внести, если решите использовать решение @ birgire, а не мое решение для настраиваемого поля

ЧАСТЬ ПЕРВАЯ ТОЧКА ПЕРВАЯ

Ваш первый блок кода, в котором вы запрашиваете свои термины, а затем запускаете пользовательский запрос дляeachterm, чтобы получить сообщения, назначенные терминам, чрезвычайно дороги. Как вы говорите, у вас есть большое количество терминов. С любым количеством терминов, вы действительно сильно ударяете по БД.

Вы можете проверить это, выполнив echo get_num_queries() после своего кода. Это покажет, сколько запросов к базе данных вы фактически делаете на этой конкретной загрузке страницы. Я бы посоветовал вам сесть, прежде чем делать это ;-)

( ПРИМЕЧАНИЕ: Сначала получите тест. Удалите весь код, затем запустите echo get_num_queries(), запишите, замените код и снова запустите echo get_num_queries() и вычтите два чтобы получить точный счет )

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

/**
 * Function get_name_banned_removed()
 *
 * A helper function to handle removing banned words
 * 
 * @param string $tring  String to remove banned words from
 * @param array  $banned Array of banned words to remove
 * @return string $string
 */
function get_name_banned_removed( $string = '', $banned = [] )
{
    // Make sure we have a $string to handle
    if ( !$string )
        return $string;

    // Sanitize the string
    $string = filter_var( $string, FILTER_SANITIZE_STRING );

    // Make sure we have an array of banned words
    if (    !$banned
         || !is_array( $banned )
    )
        return $string; 

    // Make sure that all banned words is lowercase
    $banned = array_map( 'strtolower', $banned );

    // Trim the string and explode into an array, remove banned words and implode
    $text          = trim( $string );
    $text          = strtolower( $text );
    $text_exploded = explode( ' ', $text );

    if ( in_array( $text_exploded[0], $banned ) )
        unset( $text_exploded[0] );

    $text_as_string = implode( ' ', $text_exploded );

    return $string = $text_as_string;
}

Этот код должен идти в functions.php или внутри пользовательского плагина ( предпочтительно )

Теперь, когда у нас есть это, давайте посмотрим на следующую часть

ЧАСТЬ ПЕРВАЯ ТОЧКА ВТОРАЯ

ПРИМЕЧАНИЕ: Если вы собираетесь использовать метод @ birgire для удаления запрещенных слов и сортировки по измененным заголовкам сообщений, то вы можете полностью пропустить эту часть, как мы будет устанавливать скрытое настраиваемое поле, по которому мы будем сортировать )

Вкратце, вот мое решение по приведенной выше ссылке, этот код ( который должен входить в плагин или functions.php) и должен запускаться только один раз, чтобы установить скрытое настраиваемое поле с именем _custom_sort_post_title для каждого сообщение. Это сохраняет заголовок поста с удаленным ведущим забаненным Word

( БОЛЬШОЕ ПРИМЕЧАНИЕ: я сильно отредактировал версию исходного кода из моего ответа в ссылке )

add_action( 'wp', function ()
{
    add_filter( 'posts_fields', function ( $fields, \WP_Query $q ) 
    {
        global $wpdb;

        remove_filter( current_filter(), __FUNCTION__ );

        // Only target a query where the new custom_query parameter is set with a value of custom_meta_1
        if ( 'custom_meta_1' === $q->get( 'custom_query' ) ) {
            // Only get the ID and post title fields to reduce server load
            $fields = "$wpdb->posts.ID, $wpdb->posts.post_title";
        }

        return $fields;
    }, 10, 2);

    $args = [
        'post_type'        => 'release',       // Set according to needs
        'posts_per_page'   => -1,              // Set to execute smaller chucks per page load if necessary
        'suppress_filters' => false,           // Allow the posts_fields filter
        'custom_query'     => 'custom_meta_1', // New parameter to allow that our filter only target this query
        'meta_query'       => [
            [
                'key'      => '_custom_sort_post_title', // Make it a hidden custom field
                'compare'  => 'NOT EXISTS'
            ]
        ]
    ];
    $q = get_posts( $args );

    // Make sure we have posts before we continue, if not, bail
    if ( !$q ) 
        return;

    foreach ( $q as $p ) {
        $new_post_title = strtolower( $p->post_title );

        if ( function_exists( 'get_name_banned_removed' ) )
            $new_post_title = get_name_banned_removed( $new_post_title, ['the'] );

        // Set our custom field value
        add_post_meta( 
            $p->ID,                    // Post ID
            '_custom_sort_post_title', // Custom field name
            $new_post_title            // Custom field value
        );  
    } //endforeach $q
});

После удаления этого кода единственный код, который вам понадобится в functions.php или плагине, будет следующим: ( ПРИМЕЧАНИЕ: Мы добавим еще немного работы к этому действию вЧАСТЬ ВТОРАЯ)

add_action( 'transition_post_status', function ( $new_status, $old_status, $post )
{
    // Make sure we only run this for the release post type
    if ( 'release' !== $post->post_type )
        return;

    $text = strtolower( $post->post_title );   

    if ( function_exists( 'get_name_banned_removed' ) )
        $text = get_name_banned_removed( $text, ['the'] );

    // Set our custom field value
    update_post_meta( 
        $post->ID,                 // Post ID
        '_custom_sort_post_title', // Custom field name
        $text                      // Custom field value
    );
}, 10, 3 );

Этот код гарантирует, что в каждом новом опубликованном сообщении или в каждом измененном сообщении настраивается соответствующее поле _custom_sort_post_title.

ЧАСТЬ ВТОРАЯ

Это та часть, которая действительно может стать дорогой. Просто получить все термины, просмотреть их и выполнить соответствующие запросы - этоNOTопция здесь, так как это действительно дорогая операция с БД.

Нам нужно будет выполнить только один запрос, чтобы получить все наши идентификаторы постов, обновить кэш терминов, использовать get_object_term_cache() для получения терминов постов, отсортировать массив идентификаторов в соответствии с терминами, к которым они относятся, и затем безопасно наши результаты в переходном процессе. Мы будем хранить только идентификаторы постов во время переходного процесса, так как мы не хотим помещать огромное количество данных постов в грязный сериализованный массив

Мы будем во многом полагаться на функцию get_name_banned_removed() для создания имен терминов и публикаций заголовков с удаленными запрещенными словами.

НЕСКОЛЬКО ЗАМЕЧАНИЙ

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

КОД

/**
 * Function get_sorted_post_ids_terms_and_fields()
 *
 * Return a sorted array of post ids. These ID's are sorted according to
 * - Post title with the banned words removed before sorting
 * - Post terms with the banned words removed before sorting
 *
 * @param string $post_type Post type to get posts from Default 'release'
 * @param string $taxonomy  Taxonomy  to get posts from Default 'game'
 * @return array $ids
 */
function get_sorted_post_ids_terms_and_fields( $post_type = 'release', $taxonomy = 'game' )
{
    $array_combine = [];

    // Sanitize our post type and taxonomy names
    if ( 'release' !== $post_type )
        $post_type = filter_var( $post_type, FILTER_SANITIZE_STRING );

    if ( 'game' !== $taxonomy )
        $taxonomy = filter_var( $taxonomy, FILTER_SANITIZE_STRING );

    // Make sure that the taxonomy exist to avoid bugs later on
    if ( !taxonomy_exists( $taxonomy ) )
        return $array_combine;

    // Our taxonomy exist, let's continue
    // Create a unique transient name
    $transient_name = 'spbtaf_' . md5( $taxonomy.$post_type );    

    if ( false === ( $array_combine = get_transient ( $transient_name ) ) ) {

        // Set our query arguments. Note, we will not do any sorting here
        $args = [
            'fields'         => 'ids', // Only get post ID's
            'post_type'      => $post_type,
            'posts_per_page' => -1,
            'meta_key'       => '_custom_sort_post_title', // Remove if you use @birgire's solution
            'orderby'        => 'meta_value',               // Change to '_custom' if you use @birgire's solution
            'order'          => 'ASC',
            'tax_query'      => [
                [
                    'taxonomy' => $taxonomy,
                    'operator'  => 'EXISTS'
                ]
            ],     
        ];
        $ids = get_posts( $args );

        // Make sure we have posts
        if ( $ids ) {

            // Update the object term cache, saves plenty db time and calls
            update_object_term_cache( $ids, $post_type );

            $term_post_ids_array = [];
            $term_names          = [];

            // Loop through the posts and save in an array
            foreach ( $ids as $id ) {

                // Get the post terms from our post term cache
                $terms = get_object_term_cache( $id, $taxonomy );

                // Loop through the terms. We definitely have terms
                foreach ( $terms as $term ) {

                    // Remove the banned words from the term name
                    $term_name = strtolower( $term->name );

                    if ( function_exists( 'get_name_banned_removed' ) ) 
                        $term_name = get_name_banned_removed( $term_name, ['the'] );

                    // Save the term name and post ids in an array
                    $term_post_ids_array[$term_name][] = $id;

                    // Save the real term names in an array
                    $term_names[$term_name] = $term->name;

                } //endforeach $terms 
                unset( $term ); 

            } //endforeach $ids
            unset( $id );

            // Sort the array according to our modified term ids
            ksort( $term_post_ids_array );
            ksort( $term_names );

            // Lets replace the modified term names with their proper names
            $array_combine = array_combine( $term_names, $term_post_ids_array );

        } // endif $ids

        // Set the transient
        set_transient( $transient_name, $array_combine, 30*DAY_IN_SECONDS );    
    } // endif get_transient

    return $array_combine;
}

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

  • термин, к которому они принадлежат, с удаленными ведущими запрещенными словами ( как the)

  • заголовок сообщения с удаленным ведущим забаненным словом

Массив также сортируется в соответствии с термином

Переходный процесс установлен на 30 дней, вы можете настроить его по мере необходимости.

Нам нужно удалить и сбросить переходный процесс при публикации нового сообщения или при обновлении, удалении или восстановлении сообщения. Для этого мы будем использовать ловушку действия transition_post_status. ( Чтобы все было аккуратно и вместе, давайте объединим действие изPART ONE POINT TWOс этим действием. Я выделил раздел, который вы можете удалить, если вы сортируете с помощью @ birgire's пользовательский фильтр )

add_action( 'transition_post_status', function ( $new_status, $old_status, $post )
{
    /* ----------START DELETE IF YOU USE @birgire's SORTING FILTER------------*/
    // Make sure we only run this for the release post type
    if ( 'release' !== $post->post_type )
        return;

    $text = strtolower( $post->post_title );   

    if ( function_exists( 'get_name_banned_removed' ) )
        $text = get_name_banned_removed( $text, ['the'] );

    // Set our custom field value
    update_post_meta( 
        $post->ID,                 // Post ID
        '_custom_sort_post_title', // Custom field name
        $text                      // Custom field value
    );
    /* -------------END DELETE IF YOU USE @birgire's SORTING FILTER------------*/

    global $wpdb;

    // Delete the transients
    $wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient%_spbtaf_%')" );
    $wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient_timeout%_spbtaf_%')" );

    // Reset the transient
    if ( function_exists( 'get_sorted_post_ids_terms_and_fields' ) )
        get_sorted_post_ids_terms_and_fields(); //REMEMBER TO SET POST TYPE AND TAXONOMY

}, 10, 3 );

Как вы можете видеть, мы сбрасываем переходный процесс в действии transition_post_status, это также снимает большую нагрузку с внешнего интерфейса

ЧАСТЬ ТРЕТЬЯ

Цикл немного сложнее. У нас есть многомерный массив имен терминов и идентификаторов записей из функции get_sorted_post_ids_terms_and_fields(). Мы должны быть умными, чтобы наши дб-звонки и т.д. были как можно ниже. Сложнее всего получить полные объекты из их соответствующих идентификаторов. Кроме того, поскольку сообщения принадлежат нескольким терминам, у нас также есть дубликаты идентификаторов.

ПЛАН

Мы будем использовать пользовательский запрос, чтобы получить все сообщения. У нас есть небольшая проблема, так как WP_Query не возвращает повторяющиеся сообщения. В этом и заключается хитрость, WP_Query добавляет сообщения, которые он возвращает, в кеш. Когда сообщение находится в кеше, мы можем запрашивать его снова и снова с помощью get_post(), не вызывая db. Это умная часть всего кода.

Во-первых, нам также нужен способ сгладить многомерный массив, чтобы захватить все post_ids перед передачей его в WP_Query

/**
 * Function flatten_array()
 *
 * Function to flatten an array and get all array values
 * Special thanks to zdenko
 * @link https://Gist.github.com/kohnmd/11197713
 *
 * @param array  $array The multidimensional array to flatten
 * @return array $array The flattened array
 */
function flatten_array( $array ) 
{
    // Make sure $array is an array, if not return $array as an array
    if ( !is_array( $array ) )
        return [$array];

    return array_reduce( $array, function ( $a, $b ) {
            return array_merge( $a, flatten_array( $b ) ); 
        }, [] );
}

Что мы сделаем сейчас, так это запросим наши сообщения из сглаженного массива идентификаторов, чтобы сохранить их в кэше сообщений. Для этого мы будем использовать пользовательский запрос SQL по следующим причинам.

  • Это сверхбыстрый

  • Нам не нужны никакие фильтры или действия для изменения этого запроса.

  • Вся тяжелая работа уже была выполнена в get_sorted_post_ids_terms_and_fields(). Все, что нам нужно сделать сейчас, это взять идентификаторы из этой функции и получить полные объекты post.

Как только мы получим полные сообщения, мы можем использовать update_post_cache, чтобы добавить наши сообщения в кеш сообщений

/**
 * Function set_posts_to_cache()
 *
 * Function to query all the full post objects who's ID's is in the 
 * get_sorted_post_ids_terms_and_fields() function and then to add these
 * post objects into the post cache so we can query them over and over again 
 * with get_post()
 *
 * @param string $post_type Post type to get posts from Default 'release'
 * @param string $taxonomy  Taxonomy  to get posts from Default 'game'
 */
function set_posts_to_cache( $post_type = 'release', $taxonomy = 'game' )
{
    global $wpdb;

    // Check if the taxonomy exists
    if ( !taxonomy_exists( $taxonomy ) ) 
        return false;

    // Sanitize the taxonomy name
    $taxonomy = filter_var( $taxonomy, FILTER_SANITIZE_STRING );

    // Sanitize the post type
    if ( 'release' !== $post_type )
        $post_type = filter_var( $post_type, FILTER_SANITIZE_STRING );

    // Get our post ID's

    if ( function_exists( 'get_sorted_post_ids_terms_and_fields' ) ) {

        $combined_array = get_sorted_post_ids_terms_and_fields( $post_type, $taxonomy );

        if ( $combined_array ) {

            if ( function_exists( 'flatten_array' ) ) {

                // Flatten our array in order to pass it to WP_Query    
                $flatten_array = flatten_array( $combined_array );
                $unique_ids    = array_unique(  $flatten_array  );
                $string_ids    = implode( ', ', array_map( 'absint', $unique_ids ) );

                /**
                 * Run our custom SQL query and add our posts in cache
                 *
                 * We only need to get the posts by ID and post type. Remember, the function
                 * get_sorted_post_ids_terms_and_fields() has already taken care of all the hard 
                 * work. All this query needs to do is to retrieve the posts which ID's are returned 
                 * by get_sorted_post_ids_terms_and_fields() to add the posts in cache
                 */
                $posts_to_cache = $wpdb->get_results( 
                    $wpdb->prepare( 
                        "SELECT $wpdb->posts.*
                        FROM $wpdb->posts
                        WHERE 1=1
                        AND $wpdb->posts.ID IN ($string_ids)
                        AND $wpdb->posts.post_type = %s
                        ORDER BY $wpdb->posts.post_date DESC
                        LIMIT 0, %d",
                        $post_type,
                        count( $unique_ids )
                    )
                );  
                // Update the post cache
                update_post_caches( $posts_to_cache );
            } // endif function_exists( 'flatten_array' )
        } // endif if ( $combined_array )
    } // endif ( function_exists( 'get_sorted_post_ids_terms_and_fields' ) )
}

Давайте посмотрим на цикл сейчас

if ( function_exists( 'get_sorted_post_ids_terms_and_fields' ) ) {

    $combined_array = get_sorted_post_ids_terms_and_fields();

    // Make sure we have a valid array
    if ( $combined_array ) {

        if ( function_exists( 'set_posts_to_cache' ) ) {
            // Set all our posts into the post cache. remember to pass the correct post type and taxonomy
            set_posts_to_cache( 'release', 'game');

            // Set a variable to hold the first letter of the term name
            $first_letter = '';
            foreach ( $combined_array as $term_name=>$post_ids ) {
                // Display the first letter from the terms
                $term_name_modified = strtolower( $term_name );
                if ( function_exists( 'get_name_banned_removed' ) ) 
                    $term_name_modified = get_name_banned_removed( $term_name_modified, ['the'] );

                $starting_letter = strtoupper( mb_substr( $term_name_modified, 0, 1 ) );

                if ( $first_letter !== $starting_letter )
                    echo '<p>' . $starting_letter . '</p>'; 

                // Update the $first_letter variable

                $first_letter = $starting_letter;
                // Display the term name above the posts
                echo $term_name . '</br>';

                // Apply the get_post() function to all post ids to get full posts objects
                $posts_array = array_map( 'get_post', $post_ids );

                // Now that we have full posts, lets display them in our loop
                foreach ( $posts_array as $post ) {
                    setup_postdata( $post );

                    // APPLY YOUR LOOP AS PER NORMAL AS PER YOUR LINK. 
                    echo '<li>' . get_the_title() . '</li>';

                } // endforeach $posts_array

                wp_reset_postdata(); // VERY VERY IMPORTANT
            } // endforeach $combined_array

        } // endif function_exists flatten_array

    } // endif $combined_array

} // endif function_exists get_sorted_post_ids_terms_and_fields

Ваши сообщения должны теперь отображаться следующим образом:

  • Все сообщения отсортированы в алфавитном порядке по термину, к которому они относятся, в соответствии с названием сообщения с забаненным словом, удаленным в процессе первоначальной сортировки.

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

  • Все термины отсортированы по букве, название которой начинается с запрещенных слов, удаленных при первоначальной сортировке.

Вам просто нужно применить свой собственный стиль и разметить в цикле

РЕЗУЛЬТАТЫ ИСПЫТАНИЙ - ДОКАЗАТЕЛЬСТВО IS В ПУДИНГЕ, НЯММЬЕ !!!

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

  • вызовы на 6 дБ за 0,16 секунды

  • вызовы на 5 дБ примерно за 0,14 секунды

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

Ради интереса я скопировал цикл из вашего первого блока кода и получил следующий результат

  • 73 запроса за 0,5 секунды

Огромная разница, подтвердила мою точку зрения ;-)

ЧАСТЬ ПОД СТРОИТЕЛЬСТВОМ

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

Какое бы решение я ни предложил, оно не повлияет на части 1 и 2 моего ответа. Часть третья определенно будет затронута и потребует некоторого переписывания

1
Pieter Goosen