web-dev-qa-db-fra.com

Limiter le nombre de messages personnalisés affichés sur la page de taxonomie

J'utilise un type de message personnalisé qui utilise deux taxonomies "couleur" et "style". J'ai un script ( de ce fil ) qui les regroupe afin que lorsque vous êtes sur une page de taxonomie des couleurs, ils soient regroupés par style, comme suit:

Bleu> Style 1

  • Produit 1
  • Produit 2
  • Produit 3
  • Produit 4
  • Produit 5

Bleu> Style 2

  • Produit 1
  • Produit 2
  • Produit 3
  • Produit 4
  • Produit 5

Maintenant tout cela fonctionne très bien, mais il retourne CHAQUE poste. Je veux le limiter aux trois premiers messages pour chaque style. Je sais que je peux faire quelque chose comme ce qui suit, mais cela limite les posts pour toute la page et non par style. De l'aide? :)

//limit to three per style
add_action('pre_get_posts', 'change_tax_num_of_posts' );

function change_tax_num_of_posts( $wp_query ) {

    if( is_tax('colour') && is_main_query() ) {

      $wp_query->set('posts_per_page', 3);

    }

}
2
caffeinehigh

Comme je l'ai dit dans les commentaires, cela demandera du travail. En bref, vous aurez besoin des éléments suivants:

  • Obtenez tous les termes de la taxonomie style. Ici, nous voudrions seulement les identifiants de terme

  • Obtenez le tax_query actuel de la taxonomie colour. Utilisez chaque terme de la taxonomie style et créez un nouveau tax_query pour obtenir des publications à partir du terme de la page actuelle et du terme faisant l'objet d'une boucle à partir de la taxonomie style.

  • Exécutez une requête personnalisée sur chaque terme de la taxonomie style pour obtenir un tableau d'identifiants de publication pour chaque terme. Ici, vous voudriez ajouter tous vos paramètres personnalisés. Nous utiliserons la commande de cette requête personnalisée comme commande postérieure

  • Transmettez le tableau d'identifiants de publication à la requête principale. Ici, vous ne voudriez pas ajouter de tri personnalisé, etc. Nous allons utiliser la séquence des identifiants de post dans le tableau post id pour le tri

QUELQUES NOTES AVANT LE CODE:

  • Le code nécessite PHP 5.4+ en raison de l'utilisation d'une syntaxe de tableau courte ([]). Vous ne devriez pas non plus utiliser une version antérieure à PHP 5.4. Si toutefois vous le faites, remplacez simplement la syntaxe de tableau court par l'ancienne syntaxe de tableau (array()). Par exemple, get_terms( $taxonomy, ['fields' => 'ids'] ) devrait devenir get_terms( $taxonomy, array( 'fields' => 'ids' ) )

  • J'ai mis en place un système transitoire pour réduire la charge supplémentaire résultant de tout le travail supplémentaire que nous devons faire. Ce transitoire est configuré pour expirer dans une semaine, vous pouvez l’ajuster pour qu’il soit plus long ou plus court. Le transitoire sera automatiquement supprimé lorsqu’une nouvelle publication sera publiée, supprimée, non supprimée ou mise à jour.

  • J'ai très bien commenté le code afin que vous puissiez suivre et donner un sens à ce que je faisais au fur et à mesure

  • Vous pouvez étendre et modifier au besoin. Assurez-vous de vérifier mes commentaires

  • Avec ce nouveau code, vous pouvez supprimer mon idée complète de tri comme décrit dans ma réponse liée sur SO . Le code donné dans cette réponse devrait prendre en charge ce tri. Tous les ajustements que vous souhaitez effectuer doivent être effectués dans les requêtes personnalisées et les appels get_terms. N'oubliez pas de vider vos transitoires après chaque modification, ou mieux, décommentez les appels transitoires et revenez à la normale une fois que vous êtes satisfait de toutes vos modifications.

LE CODE:

Comme toujours, nous utiliserons pre_get_posts pour modifier la requête principale selon les besoins.

add_action( 'pre_get_posts', function ( $q )
{       
    if (    !is_admin() // Targets only front end queries
         && $q->is_main_query() // Targets only main query
         && $q->is_tax( 'colour' ) // Targets only taxonomy pages
    ) {

        /** 
         * To save on the extra work that we need to do to get our results,
         * lets save everything in a transient. We will save the string of post ids
         * in the transient. 
         *
         * We will only delete and recreate this transient when a new post is published,
         * deleted, undeleted or updated. This will save us a lot of extra hard work
         * on every page load
         *
         * @link https://codex.wordpress.org/Transients_API
         */
        $queried_object = get_queried_object(); // Get the current queried object to build a unique transient name
        /**
         * Use md5 to build a unique transient name to avoid any conflicts
         * The code below will create a unique transient name which will look like this
         * "colourtax_1ac37e97ee207e952dfc2b8f7eef110f"
         *
         * Note, this should NOT be longer that 45 characters else the transient will be regenerated
         * on each page load. Transients are expensive to create, so don't want to recreate this on every
         * page load due to a name being to long. As a quick guide the md5 part generate a 32 character string,
         * so the "colourtax_" part should be a maximum of 13 characters
         */
        $unique_transient_name = 'colourtax_' . md5( $queried_object->taxonomy . $queried_object->slug . $queried_object->term_id );
        if ( false === ( $post_ids_array = get_transient( $unique_transient_name ) ) ) {

            // Gets the current tax_query
            $tax_query = $q->tax_query->queries; 
            // Choose the taxonomy to sort by
            $taxonomy = 'style'; 
            // Set the variable to hold the sorted post ids according to terms
            $post_ids_array = [];

            /**
             * Get all the terms from the selected taxonomy to sort by. Just get term ids
             * Add additional arguments here as needed
             * 
             * @link https://codex.wordpress.org/Function_Reference/get_terms
             */
            $terms = get_terms( $taxonomy, ['fields' => 'ids'] ); 
            if (    $terms // Check if the array has valid terms, not empty
                 && !is_wp_error( $terms ) // Check that we do not have any error
            ) { 
                // Define a variable to hold all post ID
                $posts_ids = '';
                foreach ( $terms as $term ) {
                    /**
                     * NOTE: You would want to do everything here
                     *
                     * Build our query args, add all your relevant arguments here
                     * You should extend this to include your custom parameter values
                     * like meta_queries en sorting order.
                     * Do a var_dump( $wp_query ) and use the relevant arguments from
                     * there to make this dynamic
                     */
                    $args = [
                        'post_type' => 'any',
                        'posts_per_page' => 3, // Get only 3 posts per term
                        'fields' => 'ids', // Only get post ids to make query faster and more lean
                        // Build a tax_query to add additional terms from selected taxonomy to sort by  
                        'tax_query' => [ 
                            $tax_query, // Our default tax_query from the taxonomy page
                            [
                                'taxonomy' => $taxonomy,
                                'terms' => $term,
                                'include_children' => false,
                            ],
                        ],
                    ];
                    // Return an array of post ids only
                    $posts_array = get_posts( $args );
                    // First check if we have posts to avoid bugs in our code
                    if ( $posts_array ) {
                        // Break the ids array up into a string for later processing
                        foreach ( $posts_array as $v )
                            $posts_ids .= ' ' . $v;
                        unset( $v );    
                    } //endif $posts_array

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

                // ADDITIONAL, CAN DELETE THE FOLLOWING SECTION IF YOU WANT TO. READ COMMENTS BELOW

                /**
                 * You can remove the following section. The idea here is as follow:
                 * Any post without a term in the style taxonomy will not be displayed on
                 * a colour taxonomy term page. To avoid this, we will need to get all posts
                 * that does not have a post in style taxonomy. This posts will be displayed last
                 * on the page
                 *
                 * If you are very sure that all posts are tagged in a colour AND style taxonomy
                 * term, then you can remove this section, this is really just a fall back
                 */
                $args_additional = [
                    'post_type' => 'any',
                    'posts_per_page' => 3, // Get only 3 posts without style taxonomy term, adjust as needed
                    'fields' => 'ids', // Only get post ids to make query faster and more lean
                    // Build a tax_query to get posts that is not tagged in style taxonomy  
                    'tax_query' => [ 
                        $tax_query, // Our default tax_query from the taxonomy page
                        [
                            'taxonomy' => $taxonomy,
                            'terms' => $terms,
                            'include_children' => false,
                            'operator' => 'NOT IN', // Posts should not have these terms from style taxonomy
                        ],
                    ],
                ];
                // Return an array of post ids only
                $posts_array_2 = get_posts( $args_additional );
                // First check if we have posts to avoid bugs in our code
                if ( $posts_array_2 ) {
                    // Break the ids array up into a string for later processing
                    foreach ( $posts_array_2 as $v )
                        $posts_ids .= ' ' . $v;
                    unset( $v );    
                } //endif $posts_array

                // STOP DELETING HERE!!

                // Create an array of post ids from the $posts_ids string
                $post_ids_array = explode( ' ', ltrim( $posts_ids ) );

            } //endif $terms

            /**
             * Set the transient if it does not exist. 
             * NOTE: We will choose a week for expiry date, set as needed
             *
             * @link https://codex.wordpress.org/Transients_API#Using_Time_Constants
             */     
            set_transient( $unique_transient_name, $post_ids_array, 7 * DAY_IN_SECONDS );   
        } // endif transient check

        /**
         * Check if we have an array of post ID's before changing anything on the tax page
         *
         * Here we will alter the main query. You do not want to add or remove anything
         * here. Any custom parameters like sorting should be done in the custom queries
         * above
         *
         * DO NOT CHANGE ANYTHING IN THE CODE BELOW EXCEPT posts_per_page
         */
        if ( !empty( $post_ids_array ) ) {
            $q->set( 'post__in', $post_ids_array ); // Posts to get as set in our array, max of 3 posts per term
            $q->set( 'orderby', 'post_in' ); // Sort our posts in the order it is passed in the post__in array
            $q->set( 'order', 'ASC' );
            $q->set( 'posts_per_page', -1 ); // You can change this, if I remember, you need all posts on one page
        }

    } //endif conditional checks for query
});

Cela s’occupe de tout sauf du rinçage des transitoires après publication, suppression, etc.

Le code suivant va s'en occuper. Chaque fois qu'un article est mis à jour, publié, mis à la corbeille ou non, le hook transition_post_status se déclenche. Nous allons donc utiliser cette logique pour supprimer tous nos transitoires contenant une partie du nom colourtax_.

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

Ok, je pense avoir trouvé un moyen de le faire. Bien que je dois dire que je ne l'ai pas encore testé et que ce n'est probablement pas la meilleure solution. Si heureux de voir d'autres solutions.

Ce que j’ai fait est de créer une méta-boîte dans mon message personnalisé avec un bouton radio avec les options "en vedette" et "non en vedette". Je règle les trois publications personnalisées de chaque groupe que je souhaite afficher, puis je filtre la requête principale avec la clé méta correspondante. Ainsi:

function colour_tax_featured($query) {

if( is_tax('colour') && $query->is_main_query() ) {

    $query->set('meta_key', 'meta_box_featured_colour');
        $query->set('meta_value', 'featured_colour');
    return $query;
}

 }

    add_action('pre_get_posts', 'colour_tax_featured' );
0
caffeinehigh