web-dev-qa-db-fra.com

Tri d'une liste d'articles publiés sous une liste de termes associés (à trier sans les articles initiaux)

J'ai une série de problèmes de tri sur une page que j'essaie de résoudre, mais jusqu'à présent sans résultat.

Tri d'une liste de publications du CPT répertoriées sous les termes de taxonomie personnalisée associés

J'ai trouvé ce morceau de code dans une réponse à cette question , qui fonctionne parfaitement pour renvoyer une liste de tous les termes de taxonomie personnalisés avec une liste de types de publication personnalisée associés sous chacun d'eux.

$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;
     }
}

Toutefois, la liste des types de publication personnalisée affichés sous chaque terme de taxonomie n'est pas triée (ou elle peut être triée par date de publication) et je souhaiterais la trier par ordre alphabétique (ou même mieux - via le tri personnalisé affiché dans ce fil et la question en dessous de celui-ci).

Normalement, j'ajouterais simplement un 'orderby' => 'title' quelque part dans le mélange, mais cela ne semble pas fonctionner ici ou je n'arrive pas à comprendre où il devrait être ajouté.

Est-ce que quelqu'un sait comment obtenir ces triés?

UPDATE

J'ai essayé d'ajouter 'orderby' => 'title' après 'post_type' => 'custom_post_type' dans $args qui n'a eu aucun effet.

En ignorant l'article initial 'Le' des termes de taxonomie personnalisée renvoyés

À l'aide d'un code provenant de cette entrée de blog _ et ces correctifs et suggestions d'amélioration J'ai réussi à obtenir une liste de toutes les publications sous dans un type d'article personnalisé et à les afficher par ordre alphabétique tout en ignorant le 'The' dans les titres de poste.

Maintenant, j'aimerais aussi que ma liste de termes de taxonomie personnalisée soit renvoyée de la même manière, si possible.

C'est le code utilisé pour trier les articles par ordre alphabétique en ignorant le 'Le' initial:

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;
}

Cela me permet d’utiliser ce filtre en utilisant un paramètre _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 );

J'ai essayé de déconner avec le code ci-dessus pour voir si je pouvais créer une fonction qui s'appliquerait aux termes de taxonomie au lieu de posts, mais je suis assez nouvelle dans tout cela et je n'ai pas pu créer quoi que ce soit qui fonctionne de cette façon. .

Est-il possible de réécrire le code pour l'appliquer aux termes de taxonomie dans une liste au lieu de posts?

Limiter la liste des termes de taxonomie renvoyés + les publications associées à ceux commençant par une lettre spécifique

Pour le moment, la liste des termes de taxonomie et des postes associés renvoyés est très longue. Pour que cela soit un peu plus facile à parcourir lorsque je parcours la liste, j'aimerais la découper en 5 ou 6 pages en affichant les termes par ordre alphabétique de A-E, F-J, etc.

Si ce n'est pas faisable, je serais d'accord pour le diviser entièrement en A, B, C, D, etc.

J'ai essayé de parcourir les questions précédentes à ce sujet, mais je n'ai rien trouvé qui semblait fonctionner à distance pour moi.

UPDATE

J'ai trouvé cet article qui semble faire ce que je veux, mais je n'arrive pas à le faire fonctionner sur mon site. C'est le code que j'ai ajouté avec des modifications basées sur le post lié. Il ne fait que renvoyer une liste complètement vide.

$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>';
    }
    }
}
}

UPDATE - Ajouté le code de PieterGoosen

J'ai ajouté le code de la réponse de @ PieterGoosen ci-dessous à mon fichier functions.php (le code est identique à celui de la réponse) et à mon fichier de modèle de page ( le code avec le contenu de ma boucle ajoutée peut être vu ici } ).

Ce que j'obtiens est en partie correct, mais il y a encore des choses qui ne vont pas. Avec le nouveau code, je reçois une liste de tous les articles du release CPT triés par 1 terme game associé. Le terme choisi est celui qui commence par la lettre la plus ancienne de l'alphabet - comme dans Asteroids, celle-ci sera choisie par-dessus Pac-Man, mais par-dessus Pac-Man, par-dessus Space Invaders.

Ce qu'il devrait afficher est une liste de tous les termes game et, sous chaque terme, une liste de tous les postes release associés. En outre, il semble que chaque publication release ne soit affichée qu'une seule fois, mais de manière optimale, j'aimerais les faire réapparaître sous chaque terme game si plusieurs personnes y sont associées.

Cependant, la fonction de tri semble bien fonctionner. Ce nouveau code ignore "le" dans tous les titres de publication et il apparaît qu'il est également ignoré dans les noms de terme en fonction du tri en cours (il serait plus clair si les noms de terme étaient affichés).

UPDATE 2 - Test du nouveau code de @ PieterGoosen

J'ai mis à jour mon code avec le code mis à jour et cela fonctionne comme un charme. Tout ce que j'ai à faire est d'appliquer du contenu de style et de boucle.

Pour référence, cette solution a VASTLY amélioré le nombre de requêtes de base de données sur ma page par rapport à mon ancien code (comme indiqué en haut de cette question. Utiliser get_num_queries() pour vérifier - mon ancien code contenait 3166 requêtes de base de données. Avec le nouveau code, je suis à la place de 33 (+ maintenant, en fait, toutes les données que je veux afficher + la page se charge plus rapidement).

2
rpbtz

C'est une question très intéressante, qui peut entraîner un processus très coûteux et gourmand en ressources, ce qui peut réellement ralentir considérablement votre page.

PRÉLUDE

Tout mon code dans cette question est basé sur le type de message et la taxonomie suivants. Par conséquent, avant d'exécuter un code, veillez à ajuster le type de message et la taxonomie à vos propres besoins.

  • Type de message personnalisé ->release

  • Taxonomie personnalisée ->game

MISE À JOUR IMPORTANTE

Etant donné que vous devez inclure tous les termes et le message appartenant à ces termes, et pas seulement trier et inclure le premier terme attribué à un message, nous devons examiner complètement une autre solution, tout en gardant à l'esprit les performances.

La nouvelle solution correspondrait parfaitement à la solution de @birgire à votre question précédente , car nous allons maintenant trier la requête elle-même et non les messages renvoyés.

Ma solution initiale à la même question que vous avez posée n'est donc plus nécessaire pour résoudre ce problème, il vous appartient donc de décider si vous souhaitez ou non créer et trier la boucle avec la personnalisation masquée champ. Ma solution utilisant le champ personnalisé reste cependant totalement valide. Parce que ma réponse initiale à cette question impliquait ma solution de terrain personnalisée, je continuerai à l'utiliser, bien que j'essaierai d'indiquer les modifications que vous pouvez apporter si vous décidez d'utiliser la solution @ birgire plutôt que ma solution de terrain personnalisée.

PREMIÈRE PARTIE POINT UN

Votre premier bloc de code où vous interrogez vos termes, puis exécutez une requête personnalisée poureachterm afin d'obtenir les publications affectées à un terme est extrêmement coûteux. Comme vous le dites, vous avez une grande quantité de termes. Avec n'importe quel nombre de termes, vous frappez vraiment la base de données vraiment très fort.

Vous pouvez vérifier cela en faisant echo get_num_queries() après votre code. Cela affichera combien de requêtes de base de données vous effectuez réellement sur cette page. Je vous suggère de vous asseoir avant de faire cela ;-)

( NOTE: Commencez par obtenir un point de repère. Supprimez tout votre code, puis exécutez echo get_num_queries(), notez-le, remplacez-le et exécutez à nouveau echo get_num_queries() et soustrayez les deux pour obtenir un compte précis )

Avant de commencer, examinons d'abord une fonction d'aide qui gérera la suppression de nos mots interdits des noms de terme et de publication. Cette fonction est importante et sera utilisée partout pour garder notre code DRY et organisé

/**
 * 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;
}

Ce code doit aller dans functions.php ou dans un plugin personnalisé ( de préférence )

Maintenant que nous avons couvert, regardons la partie suivante

PREMIÈRE PARTIE POINT DEUX

NOTE: Si vous envisagez d'utiliser la méthode de @ birgire pour supprimer les mots interdits et trier les titres de publication modifiés, vous pouvez ignorer complètement cette partie. définira le champ personnalisé masqué que nous trierons par )

Encore une fois, voici ma solution du lien ci-dessus, ce code ( qui devrait être inséré dans un plugin ou functions.php) et n’a besoin d’être exécuté qu’une seule fois pour définir un champ personnalisé masqué appelé _custom_sort_post_title à chaque poster. Cela enregistre le titre du message avec le mot interdit banni en tête

( BIG NOTE: J'ai fortement édité la version du code original de ma réponse dans le lien )

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
});

Une fois ce code supprimé, le seul code dont vous aurez besoin dans functions.php ou un plugin sera le suivant: ( NOTE: nous ajouterons encore du travail. à cette action dansPART TWO)

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 );

Ce code garantira que chaque nouvelle publication publiée, ou chaque publication modifiée, que le champ personnalisé _custom_sort_post_title est défini en conséquence.

DEUXIÈME PARTIE

C'est la partie qui peut vraiment coûter cher. Obtenir simplement tous les termes, les parcourir en boucle et interroger les publications en conséquence est une optionNOT/ car il s’agit d’une opération de base de données très coûteuse.

Ce que nous devrons faire, c'est que nous n'exécuterons qu'une requête ici pour obtenir tous nos identifiants de publication, mettre à jour le cache de termes, utiliser get_object_term_cache() pour récupérer les termes de publication, trier le tableau d'identifiants en fonction des termes auxquels ils appartiennent, puis en toute sécurité. nos résultats dans un transitoire. Nous ne ferons que sécuriser les identifiants de post-in transitoires, car nous ne voulons pas encombrer une quantité énorme de données de post dans un tableau sérialisé en désordre.

Nous allons beaucoup nous appuyer sur la fonction get_name_banned_removed() pour créer des noms de terme et publier des titres avec les mots interdits supprimés.

QUELQUES NOTES

  • J'ai rendu le code de cette section un peu plus dynamique. Au lieu de coder en dur le type de publication et la taxonomie, je leur ai fourni des arguments que vous pouvez transmettre à la fonction. Vous devriez lire les blocs de code fournis avec le code

LE CODE

/**
 * 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;
}

Cela devrait permettre à la fonction de renvoyer un tableau trié d’ID de publication classés en fonction de

  • le terme auquel ils appartiennent avec les mots les plus interdits ( comme the) est supprimé

  • poste titre avec le mot interdit interdit enlevé

Le tableau est également trié par terme

Le transitoire est défini sur 30 jours, vous pouvez l’ajuster si nécessaire.

Nous devons supprimer et réinitialiser le transitoire lorsqu'un nouveau message est publié, ou lorsqu'un message est mis à jour, supprimé ou non supprimé. Pour cela, nous utiliserons le hook d’action transition_post_status. ( Pour que tout soit bien ordonné et combiné, combinons l'action dePART ONE POINT TWOavec cette action. J'ai marqué une section que vous pouvez supprimer si vous triez avec @ birgire's filtre personnalisé )

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 );

Comme vous pouvez le constater, nous réinitialisons le transitoire dans l'action transition_post_status, cela enlève également beaucoup de charge au début du processus.

PARTIE TROIS

La boucle est un peu délicate. Nous avons un tableau multidimensionnel de noms de termes et d'ID de publication provenant de la fonction get_sorted_post_ids_terms_and_fields(). Nous devons être intelligents ici pour garder nos appels à la base de données, etc. aussi bas que possible. La partie délicate consiste à récupérer tous les objets de publication à partir de leurs identifiants respectifs. De plus, comme les messages appartiennent à plusieurs termes, nous avons également des identifiants en double.

LE PLAN

Nous allons utiliser une requête personnalisée pour obtenir tous les messages. Nous avons un léger problème ici, car WP_Query ne renvoie pas les messages en double. C'est ici que l'astuce intervient, WP_Query ajoute les publications renvoyées dans un cache. Une fois qu'une publication est dans le cache, nous pouvons l'interroger avec get_post() plusieurs fois sans passer d'appel. C'est la partie intelligente de tout le code.

Premièrement, nous avons également besoin d’un moyen d’aplatir le tableau multidimensionnel pour saisir tous les post_ids avant de le passer à 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 ) ); 
        }, [] );
}

Ce que nous allons faire maintenant, c'est interroger nos publications à partir du tableau d'ID aplaties afin de les stocker dans le cache de publication. Pour cela, nous allons utiliser une requête SQL personnalisée pour les raisons suivantes

  • C'est super rapide

  • Nous n'avons besoin d'aucun filtre ou action pour modifier cette requête

  • Tout le travail acharné était déjà fait dans la get_sorted_post_ids_terms_and_fields(). Tout ce dont nous avons besoin maintenant, c’est d’extraire les identifiants de cette fonction et d’obtenir les objets post complets.

Une fois que nous avons les publications complètes, nous pouvons utiliser update_post_cache pour ajouter nos publications dans le cache de publication.

/**
 * 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' ) )
}

Regardons la boucle maintenant

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

Vos messages devraient maintenant apparaître comme suit:

  • Tous les articles sont triés par ordre alphabétique sous le terme auquel ils appartiennent, en fonction du nom de l'article; Word supprimé a été supprimé lors du processus de tri initial.

  • Tous les termes sont triés par ordre alphabétique, les mots interdits étant retirés du tri initial. Tous les termes ont leurs messages triés sous eux

  • Tous les termes sont triés sous la lettre dont le nom commence par les mots interdits supprimés lors du tri initial

Il vous suffira d'appliquer votre propre style et de marquer la boucle.

RÉSULTATS DU TEST - LA PREUVE IS DANS LE PUDDING, NJAMMIE !!!

Après cet énorme marathon, laisse les chiffres se croiser. Sur 24 articles, avec tout le travail considérable accompli pour effacer et trier les titres des articles et les noms de termes, je me suis retrouvé avec

  • 6db appelle en environ 0,16 seconde

  • appels 5db en environ 0,14 seconde

et nous n'avons pas abusé de notre transitoire. Assez impressionnant pour un travail aussi énorme, lol.

Juste pour votre intérêt, j'ai copié la boucle de votre premier bloc de code et j'ai obtenu le résultat suivant

  • 73 requêtes en 0.5 seconde

Une différence énorme, prouvé mon point ;-)

PARTIE EN CONSTRUCTION

Si nous voulons paginer la requête en fonction de la première lettre du terme, nous aurions besoin de travail supplémentaire ici. Cette section restera en construction jusqu’à ce que j’obtienne une solutionproper.

Quelle que soit la solution proposée, elle n’affectera pas les parties 1 et 2 de ma réponse. La troisième partie sera certainement affectée et nécessitera une sorte de réécriture

1
Pieter Goosen