web-dev-qa-db-fra.com

La boucle entre les messages par catégorie donne les mêmes messages pour chaque catégorie

Pour une section spécifique de mon site Web, je parcours certaines catégories et récupère les trois derniers articles de cette catégorie et les répertorie. Ainsi:

<?php $categories = get_categories(array('exclude' => '1, 4, 9, 10, 2899')); ?>

<?php foreach ($categories as $category) : ?>
    <div class="subject">
        <h3><?php echo $category->cat_name; ?></h3>
        <ul>
            <?php $args = array(
                'cat' => $category->cat_ID,
                'posts_per_page' => 3
            ); ?>
            <?php if (false === ( $category_posts_query = get_transient( 'category_posts' ) ) ) {
                $category_posts_query = new WP_Query($args);
                set_transient( 'category_posts', $category_posts_query, 36 * HOUR_IN_SECONDS );
            }
            ?>
            <?php while($category_posts_query->have_posts()) : ?>
                <?php $category_posts_query->the_post(); ?>
                <li><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></li>
            <?php endwhile; ?>
        </ul>
    </div>
<?php wp_reset_postdata(); ?>
<?php endforeach; ?>

Cependant, le résultat n'est pas celui attendu: tous les messages sont identiques dans toutes les catégories, même s'ils n'appartiennent pas aux différentes catégories: enter image description here

Lorsque je supprime la transient pour la mise en cache, tout fonctionne comme prévu.

<?php $categories = get_categories(array('exclude' => '1, 4, 9, 10, 2899')); ?>

<?php foreach ($categories as $category) : ?>
    <div class="subject">
        <h3><?php echo $category->cat_name; ?></h3>
        <ul>
            <?php $args = array(
                'cat' => $category->cat_ID,
                'posts_per_page' => 3
            ); ?>
            <?php $category_posts_query = new WP_Query($args); ?>
            <?php while($category_posts_query->have_posts()) : ?>
                <?php $category_posts_query->the_post(); ?>
                <li><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></li>
            <?php endwhile; ?>
        </ul>
    </div>
<?php wp_reset_postdata(); ?>
<?php endforeach; ?>

Comment ajouter la synchronisation à ce dernier extrait?

1
Bram Vanroy

Je ne pense pas que vous ayez besoin de autant de transitoires, un pour chaque catégorie. Vous ne pouvez en utiliser qu'un, c'est assez. Les transitoires sont assez coûteux à configurer car ils nécessitent des requêtes de base de données supplémentaires. Vous voudrez donc en réduire l'utilisation.

Comme toujours, j'aime garder mes modèles simples, courts et agréables. J'ai donc tendance à écrire des fonctions personnalisées pour déplacer la majeure partie du code en dehors de mes modèles. Vous pouvez tout mettre dans une fonction avec un transitoire

Vous pouvez essayer quelque chose comme ceci ( requiert PHP 5.4 + )

function get_term_post_list( $taxonomy = 'category', $args = [], $query_args = [] )  
{
    /*
     * Check if we have a transient set
     */
    if ( false === ( $output = get_transient( 'term_list_' . md5( $taxonomy . json_encode( $args ) . json_encode( $query_args ) ) ) ) ) {

        /*
         * Use get_terms to get an array of terms
         */
        $terms = get_terms( $taxonomy, $args );

       if ( is_wp_error( $terms ) || empty( $terms ) )
            return null;

        /*
         * We will create a string with our output
         */
        $output = ''; 
        foreach ( $terms as $term ) {

            $output .= '<div class="subject">';
            $output .= '<h3>' . $term->name . '</h3>';
            $output .= '<ul>';

            /*
             * Use a tax_query to make this dynamic for all taxonomies
             */
            $default_args = [
                'no_found_rows' => true,
                'suppress_filters' => true,
                'tax_query' => [
                    [
                        'taxonomy' => $taxonomy,
                        'terms' => $term->term_id,
                        'include_children' => false
                    ]
                ]
            ];
            /*
             * Merge the tax_query with the user set arguments
             */
            $merged_args = array_merge( $default_args, $query_args );

            $q = new WP_Query( $merged_args );

            while($q->have_posts()) {
                $q->the_post();

                $output .= '<li><a href="' . get_permalink() . '" title="' . apply_filters( 'the_title', get_the_title() ) . '">' . apply_filters( 'the_title', get_the_title() ) . '</a></li>';

            }
            wp_reset_postdata();

            $output .= '</ul>';
            $output .= '</div>';

        }
        /*
         * Set our transient, use all arguments to create a unique key for the transient name
         */
        set_transient( 'term_list_' . md5( $taxonomy . json_encode( $args ) . json_encode( $query_args ) ), $output, 36 * HOUR_IN_SECONDS );
    }
    /*
     * $output will be atring, treat as such
     */
    return $output;
}

Quelques notes

  • Le premier paramètre, $ taxonomy, est la taxonomie à partir de laquelle les termes et les publications sont publiés. La valeur par défaut est 'catégorie'

  • Le deuxième paramètre est $args qui correspond aux arguments devant être passés à get_terms(). Pour plus d'informations, consultez get_terms()

  • Le troisième paramètre, $query_args, correspond aux arguments à transmettre à la requête personnalisée. N'oubliez pas d'éviter d'utiliser des paramètres liés à la taxonomie. Pour plus d'informations, voir WP_Query

  • Si le deuxième paramètre n'est pas défini et que le troisième paramètre est défini, passez un tableau vide au deuxième paramètre.

  • Modifier et abuser du code comme bon vous semble

USAGE

Vous pouvez maintenant utiliser la fonction comme suit dans vos modèles

$post_list = get_term_post_list( 'category', ['exclude' => '1, 4, 9, 10, 2899'], ['posts_per_page' => 3] );
if ( $post_list !== null ) {
    echo $post_list;
}

Si vous ne transmettez rien au deuxième paramètre mais au troisième, procédez comme suit (passez un tableau vide)

$post_list = get_term_post_list( 'category', [], ['posts_per_page' => 3] );
if ( $post_list !== null ) {
    echo $post_list;
}

MODIFIER

Dans une course, j'ai totalement oublié d'ajouter une fonction pour vider le transitoire lorsqu'un nouveau message est publié, mis à jour, supprimé ou supprimé. En l'état actuel de votre code, la liste ne sera mise à jour qu'à l'expiration du transitoire.

Pour éliminer le transitoire dans les conditions de post ci-dessus, utilisez simplement le crochet transition_post_status. Ajoutez ce qui suit à votre functions.php

add_action( 'transition_post_status', function ()
{
        global $wpdb;
        $wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient%_term_list_%')" );
        $wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient_timeout%_term_list_%')" );
});

EDIT 2

De votre commentaire à cette réponse

Comme vous l'avez peut-être deviné, j'aimerais utiliser cette combinaison avec mon autre question . Comment pourrais-je m'y prendre? L'exclusion des termes doit-elle avoir lieu dans get_term_post_list()? Ou faut-il que les deux fonctions soient fusionnées d'une manière ou d'une autre? (Comme je n'en ai pas besoin séparément.)

La meilleure façon d'accomplir est de fusionner les deux fonctions en une. Cela aurait le plus de sens. J'ai fusionné les deux fonctions et modifié la fonctionnalité avec les paramètres d'exclusion. Ce que j’ai fait est que vous pouvez maintenant ajouter un tableau d’identifiants de terme à exclure via le paramètre get_terms()exclude et vous pouvez également, dans la même fonction, définir un tableau de slugs à exclure. Les résultats seront fusionnés dans un seul paramètre exclude avant d'être passés à get_terms()

Voici la fonction, encore une fois je l’ai bien commentée pour la rendre facile à suivre ( Cela entre dans functions.php )

function get_term_post_list( $taxonomy = 'category', $args = [], $query_args = [], $exclude_by_slug = [] )  
{
    /*
     * Check if we have a transient set
     */
    if ( false === ( $output = get_transient( 'term_list_' . md5( $taxonomy . json_encode( $args ) . json_encode( $query_args ) ) ) ) ) {

        /*
         * Check if any array of slugs is passed and if it is a valid array
         */
        if ( is_array( $exclude_by_slug ) && !empty( $exclude_by_slug ) ) {

            foreach ( $exclude_by_slug as $value ) {

                /*
                 * Use get_term_by to get the term ID and add ID's to an array
                 */
                $term_objects = get_term_by( 'slug', $value, $taxonomy );
                $term_ids[] = (int) $term_objects->term_id;

            }

        }

        /*
         * Merge $args['exclude'] and $term_ids 
         */
        if ( isset( $args['exclude'] ) && isset( $term_ids ) ) {

            $excluded_args = (array) $args['exclude'];
            unset( $args['exclude'] );
            $args['exclude'] = array_merge( $excluded_args, $term_ids );

        } elseif ( !isset( $args['exclude'] ) && isset( $term_ids ) ) {

            $args['exclude'] = $term_ids;

        } 

        /*
         * Use get_terms to get an array of terms
         */
        $terms = get_terms( $taxonomy, $args );

       if ( is_wp_error( $terms ) || empty( $terms ) )
            return null;

        /*
         * We will create a string with our output
         */
        $output = ''; 
        foreach ( $terms as $term ) {

            $output .= '<div class="subject">';
            $output .= '<h3>' . $term->name . '</h3>';
            $output .= '<ul>';

            /*
             * Use a tax_query to make this dynamic for all taxonomies
             */
            $default_args = [
                'no_found_rows' => true,
                'suppress_filters' => true,
                'tax_query' => [
                    [
                        'taxonomy' => $taxonomy,
                        'terms' => $term->term_id,
                        'include_children' => false
                    ]
                ]
            ];
            /*
             * Merge the tax_query with the user set arguments
             */
            $merged_args = array_merge( $default_args, $query_args );

            $q = new WP_Query( $merged_args );

            while($q->have_posts()) {
                $q->the_post();

                $output .= '<li><a href="' . get_permalink() . '" title="' . apply_filters( 'the_title', get_the_title() ) . '">' . apply_filters( 'the_title', get_the_title() ) . '</a></li>';

            }
            wp_reset_postdata();

            $output .= '</ul>';
            $output .= '</div>';

        }
        /*
         * Set our transient, use all arguments to create a unique key for the transient name
         */
        set_transient( 'term_list_' . md5( $taxonomy . json_encode( $args ) . json_encode( $query_args ) ), $output, 36 * HOUR_IN_SECONDS );
    }
    /*
     * $output will be string, treat as such
     */
    return $output;
}

En ce qui concerne l’utilisation, vous devez d’abord examiner les paramètres que vous pouvez transmettre.

  • Paramètre 1 - $taxonomy -> taxonomie pour obtenir des termes. Valeur par défaut category

  • Paramètre 2 - $args -> Les arguments à transférer à get_terms(). Veuillez consulter get_terms() pour obtenir la liste complète des paramètres pouvant être transmis sous forme de tableau. Tableau vide par défaut []

  • Paramètre 3 - $query_args -> Argument personnalisé à transmettre à WP_Query. Vous ne devez pas transmettre ici les paramètres liés à la taxonomie, car cela poserait des problèmes avec la construction de surduction dans tax_query. Pour obtenir une liste complète des arguments valides pouvant être passés dans un tableau, voir WP_Query . Tableau vide par défaut []

  • Paramètre 4 - $exclude_by_slug -> Un tableau de slugs à exclure. Veuillez noter que ceci doit être un tableau valide pour que cela fonctionne. Les chaînes seront ignorées. Tableau vide par défaut []

Vous pouvez maintenant appeler la fonction dans l’un de vos fichiers de modèle en tant que

$a = get_term_post_list( 'category', ['exclude' => [1, 13, 42]], ['posts_per_page' => 3], ['term-slug-1', 'term-slug-2'] );
echo $a;

OR

$taxonomy = 'category';
$args = [
    'exclude' => [1, 13, 42]
];
$query_args = [
    'posts_per_page' => 3
];
$exclude_by_slug = [
    '0' => ['term-slug-1', 'term-slug-2']
];
$a = get_term_post_list( $taxonomy, $args, $query_args, $exclude_by_slug );
echo $a;

Note finale, si vous n'avez pas besoin de passer un paramètre spécifique, n'oubliez pas de passer un tableau vide comme

$a = get_term_post_list( 'category', [], [], ['term-slug-1'] );
echo $a;

Tout ce qui précède remplace tout votre code dans votre question

2
Pieter Goosen

Votre catégorie est un ID en cours de modification à chaque itération de la boucle et vous définissez un transitoire commun, qui donne le même résultat à chaque fois, même si l'ID de la catégorie a été modifié.

Vous devez donc enregistrer des éléments transitoires pour chaque catégorie.

set_transient( 'category_posts_' . $category->cat_ID, $category_posts_query, 36 * HOUR_IN_SECONDS );

Essayez cette solution

<?php $categories = get_categories(array('exclude' => '1, 4, 9, 10, 2899')); ?>

<?php foreach ($categories as $category) : ?>
    <div class="subject">
        <h3><?php echo $category->cat_name; ?></h3>
        <ul>
            <?php $args = array(
                'cat' => $category->cat_ID,
                'posts_per_page' => 3
            ); ?>
            <?php if (false === ( $category_posts_query = get_transient( 'category_posts_' . $category->cat_ID ) ) ) {
                $category_posts_query = new WP_Query($args);
                set_transient( 'category_posts_' . $category->cat_ID, $category_posts_query, 36 * HOUR_IN_SECONDS );
            }
            ?>
            <?php while($category_posts_query->have_posts()) : ?>
                <?php $category_posts_query->the_post(); ?>
                <li><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></li>
            <?php endwhile; ?>
        </ul>
    </div>
<?php wp_reset_postdata(); ?>
<?php endforeach; ?>
0
Sumit