web-dev-qa-db-fra.com

WP_Query et pagination sur une page de garde statique

Ces deux derniers jours, j'ai essayé de résoudre un problème avec WP_Query() et Pagination.

Un site Web pour lequel je suis un développeur utilise un thème Wordpress (Salient par ThemeNectar) incluant le plugin Visual composer. Mon travail consiste essentiellement à m'assurer que le site est juste fonctionnel. J'ai donc récemment écrit une extension pour le compositeur visuel. Cette extension utilise WP_Query() pour créer une nouvelle requête, recherche les publications dans des catégories spécifiques (avec une valeur par défaut établie), puis renvoie le résultat de cette requête.

Voici le code qui rend les publications et la pagination à l'intérieur de ce composant Visual Composer

public function renderPosts( $atts, $content = null ) {
    global $post;
    setup_postdata($post);

     extract( shortcode_atts( array(
            'foo' => 5, //default of 5
            'categoryslug' => 'news-views' // Currently news and views.
    ), $atts) );

    // For getting the Query variable on a statcci front page, you have
    // to use 'page' and not 'paged'. Weird.          
    $paged = ( get_query_var('page') ) ? get_query_var('page') : 1;


    // Two things needed: Not using the game library,
    // Definitely using the supplied slug.
    // These are two objects.

    $dontUse = get_category_by_slug('game-library');
    $catUsed = get_category_by_slug($atts->categoryslug);

    // Args for the custom query
     $query_args = array(
       'posts_per_page'   => intval($foo),
       'category__not_in' => $dontUse->term_id,
       'cat' => $catUsed->term_id,
       'page' => $paged
     );

    $custom_query = new WP_Query($query_args);                      

            $output = '<div id="blogroll">';  
            while ( $custom_query->have_posts() ) : $custom_query->the_post();

                $output .= "<div class='home_post col span_12 clear-both'>";
                $output .=      "<div class='col span_3'><a href='" . get_the_permalink() . "'>" . get_the_post_thumbnail(get_the_ID(), 'home_post_thumb') . "</a></div>";
                $output .=      "<div class='col span_9 col_last right-Edge'>";
                $output .=        "<h2 class='home_post_header'>";
                $output .=           '<a href="' . get_the_permalink() . '">' . get_the_title() . "</a>";
                $output .=        "</h2>";
                $output .=        get_the_excerpt();
                $output .=      '<a class="home-more-link" href="' . get_the_permalink() . '"><span class="continue-reading">Read More</span></a>';
                $output .=      "</div>";
                $output .= "</div>";

            endwhile;

            wp_reset_postdata();

            // Pagination not working, but it outputs just fine?
            $output .= '<div id="pagination" class="blogroll-pagination">' . home_pagination($custom_query) . '</div></div>';
            wp_reset_query();              

            return $output;  
 }

Maintenant, je suis conscient que le code pour générer le contenu est juste une chaîne géante concaténée, mais c'est uniquement parce que la fonction d'extension doit renvoyer quelque chose. A la toute fin, j'ai sorti la pagination avec l'utilisation d'une autre fonction définie ci-dessus.

Voici la fonction que j'ai créée et appelée home_pagination(query)

function home_pagination($query = null) {
    /*if ( !$query ) {
            global $wp_query;
            $query = $wp_query;
    } commented out because do I need this? */

    $big = 999999999; // need an unlikely integer

    $pagination = paginate_links( array(
            'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
            'format' => '?paged=%#%',
            'current' => max( 1, get_query_var( 'page' ) ),
            'total' => $query->max_num_pages,
            'prev_text' => '&laquo; Previous',
            'next_text' => 'Next &raquo;',

            ) );

    return $pagination;

} 

Cela fonctionnait il n'y a pas une semaine, mais je n'arrive pas à le faire fonctionner maintenant. Voici ce que j'ai essayé:

  1. Jouer avec get_query_var('page')
  2. Utiliser un plugin (Wp_page_navi)
  3. Changer où et quand wp_reset_postdata() et wp_reset_query() sont utilisés
  4. Utilisation de la solution de contournement max_num_pages pour next_posts_link() et previous_posts_link()

Ceci est sur une page de garde statique et je suis conscient que les règles sont différentes avec 'page' et 'paginé'

Intéressant à noter : Lorsque je modifie la variable 'paginée' dans les arguments de la requête, la page correspondante est renvoyée.

J'essaie de comprendre pourquoi la pagination que je présente dans cette requête ne fait ABSOLUMENT RIEN lorsque j'essaie de naviguer avec elle. C'est comme si il voulait naviguer vers/page/2 ou n'importe quel numéro, mais redirige ensuite immédiatement vers le site lui-même ...

J'envisage de ne pas placer l'appel paginate_links() dans une fonction distincte. Il ya probablement des erreurs flagrantes, mais j’ai mordu à la pagination qui ne semble plus fonctionner. Des idées sur la meilleure façon d’aborder cela? Y a-t-il quelque chose d'énorme qui me manque?

3
Morklympious

Je ne suis pas tout à fait sûr de ce que vous entendez par vous avez étendu le compositeur visuel, mais j'ai quelques préoccupations ici.

  • SoC -> De votre code, je détecte que vous utilisez un shortcode, qui devrait avoir sa propre classe séparée. Vous ne devriez pas étendre la classe à l'éditeur visuel (du moins, c'est comme ça que j'ai lu votre question). Les classes ne devraient jamais effectuer plusieurs tâches à la fois, elles devraient faire one single duty. Cela permet de garder votre classe extensible, courte, facile à entretenir, réutilisable et facile à tester

  • En étendant le point précédent, les fonctionnalités de front-end et de back-end ne doivent pas être mélangées

  • Je ne vois pas l'utilité d'utiliser global $post et de configurer les données de publication. Faire cela et ne pas réinitialiser les données postérieures par la suite aura des influences inattendues sur toutes les requêtes ultérieures et sur la requête principale. Vous devriez laisser tomber cela complètement

  • Ne jamais utiliser extract() dans les codes courts (et toute autre fonction d'ailleurs). Il est très irréalisable et impossible à vérifier et conduit à une sortie inattendue. Cela rend extrêmement difficile le débogage en cas d'échec. Pour cette raison même, il a été complètement retiré du noyau. Voir billet de train 22400

  • Étant donné que vous utilisez plusieurs conditions de catégorie et pour le rendre plus dynamique, je préférerais utiliser un tax_query pour gérer les conditions. Le gros plus ici serait que vous économiserez sur les appels de base de données car vous pouvez vous débarrasser de get_category_by_slug

  • Il n'y a pas besoin de wp_reset_query(). Ceci est utilisé avec query_posts que vous ne devriez jamais utiliser. C'est un sauteur de page.

  • Les pages de couverture et les pages uniques utilisent la variable de requête page (get_query_var( 'page' )) pour la pagination et non pas paged (get_query_var( 'paged' )) comme les autres pages. L'argument de requête pour WP_Query pour les deux est cependant le même, il devrait être paged, pas page. Le valeur du paramètre/argument paged doit être page pour les pages de garde statiques et paged pour toutes les autres pages.

Vous pouvez réécrire votre méthode ci-dessus comme suit: (CAVEAT: Non testé)

public function renderPosts( $atts ) 
{
    $attributes = shortcode_atts( array(
        'foo'     => 5, //default of 5
        'include' => 'news-views', // Currently news and views.
        'exclude' => 'game-library' // Exclude this category
    ), $atts);

    /* 
     * For getting the Query variable on a static front page, you have
     * to use 'page' and not 'paged'. Weird.
     */ 
    if ( get_query_var('paged') ) {
        $paged = get_query_var('paged'); 
    } elseif ( get_query_var('page') ) { 
        $paged = get_query_var('page'); 
    } else { 
        $paged = 1; 
    }


    /*
     * Args for the custom query
     */
    $query_args = array(
        'posts_per_page' => intval($attributes['foo']),
        'tax_query'      => array(
            array(
                'taxonomy' => 'category',
                'field' => 'slug',
                'terms' => explode( ',', str_replace( ' ', '', $attributes['include'] ) ),
                'include_children' => false
            ),
            array(
                'taxonomy' => 'category',
                'field' => 'slug',
                'terms' => explode( ',', str_replace( ' ', '', $attributes['exclude'] ) ),
                'operator' => 'NOT IN'
            )
        ),
        'paged' => $paged
    );

    $custom_query = new WP_Query($query_args); 

    $output = '';
    if ( $custom_query->have_posts() ) {  

        $output .= '<div id="blogroll">'; 

        while ( $custom_query->have_posts() ) { 

            $custom_query->the_post();

            $output .= "<div class='home_post col span_12 clear-both'>";
            $output .=      "<div class='col span_3'><a href='" . get_the_permalink() . "'>" . get_the_post_thumbnail(get_the_ID(), 'home_post_thumb') . "</a></div>";
            $output .=      "<div class='col span_9 col_last right-Edge'>";
            $output .=        "<h2 class='home_post_header'>";
            $output .=           '<a href="' . get_the_permalink() . '">' . get_the_title() . "</a>";
            $output .=        "</h2>";
            $output .=        get_the_excerpt();
            $output .=      '<a class="home-more-link" href="' . get_the_permalink() . '"><span class="continue-reading">Read More</span></a>';
            $output .=      "</div>";
            $output .= "</div>";

        }

        wp_reset_postdata();

        $output .= '<div id="pagination" class="blogroll-pagination">' . home_pagination( $custom_query ) . '</div></div>';

    }

    return $output;  
}

Rappelez-vous simplement que j’ai changé les attributs pour la lisibilité, include prend une chaîne de catégorie slugs (include='slug-1, slug-2'), séparée par des virgules. Cet attribut sera utilisé pour inclure des catégories. exclude fonctionne de la même façon (exclude='slug-1, slug-2'), sauf qu’il faut une chaîne de la catégorie slugs séparée par des virgules

MODIFIER

J'ai testé mon code et corrigé quelques petits bugs. Cela fonctionne comme prévu si je crée simplement un shortcode normal.

PREUVE DE CONCEPTION - CODE COURT

add_shortcode( 'testcode', function ( $atts )
{
    $attributes = shortcode_atts( array(
        'foo'     => 5, //default of 5
        'include' => 'news-views', // Currently news and views.
        'exclude' => 'game-library' // Exclude this category
    ), $atts);

    /* 
     * For getting the Query variable on a static front page, you have
     * to use 'page' and not 'paged'. Weird.
     */ 
    if ( get_query_var('paged') ) {
        $paged = get_query_var('paged'); 
    } elseif ( get_query_var('page') ) { 
        $paged = get_query_var('page'); 
    } else { 
        $paged = 1; 
    }


    /*
     * Args for the custom query
     */
    $query_args = array(
        'posts_per_page' => intval($attributes['foo']),
        'tax_query'      => array(
            array(
                'taxonomy' => 'category',
                'field' => 'slug',
                'terms' => explode( ',', str_replace( ' ', '', $attributes['include'] ) ),
                'include_children' => false
            ),
            array(
                'taxonomy' => 'category',
                'field' => 'slug',
                'terms' => explode( ',', str_replace( ' ', '', $attributes['exclude'] ) ),
                'operator' => 'NOT IN'
            )
        ),
        'paged' => $paged
    );

    $custom_query = new WP_Query($query_args); 

    $output = '';
    if ( $custom_query->have_posts() ) {  

        $output .= '<div id="blogroll">'; 

        while ( $custom_query->have_posts() ) { 

            $custom_query->the_post();

            $output .= "<div class='home_post col span_12 clear-both'>";
            $output .=      "<div class='col span_3'><a href='" . get_the_permalink() . "'>" . get_the_post_thumbnail(get_the_ID(), 'home_post_thumb') . "</a></div>";
            $output .=      "<div class='col span_9 col_last right-Edge'>";
            $output .=        "<h2 class='home_post_header'>";
            $output .=           '<a href="' . get_the_permalink() . '">' . get_the_title() . "</a>";
            $output .=        "</h2>";
            $output .=        get_the_excerpt();
            $output .=      '<a class="home-more-link" href="' . get_the_permalink() . '"><span class="continue-reading">Read More</span></a>';
            $output .=      "</div>";
            $output .= "</div>";

        }

        wp_reset_postdata();

        $output .= '<div id="pagination" class="blogroll-pagination">' . home_pagination( $custom_query ) . '</div></div>';

    }

    return $output;  
});

que j'utilise comme suit

[testcode include='testslug-1, testslug-2' exclude='testslug-3, testslug-4']

J'ai également testé votre fonction de pagination, qui fonctionne également comme prévu.

function home_pagination( $query = null ) 
{

    $big = 999999999; // need an unlikely integer

    if ( get_query_var('paged') ) {
        $paged = get_query_var('paged'); 
    } elseif ( get_query_var('page') ) { 
        $paged = get_query_var('page'); 
    } else { 
        $paged = 1; 
    }


    $pagination = paginate_links( 
        array(
            'base'      => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
            'format'    => '?paged=%#%',
            'current'   => $paged,
            'total'     => $query->max_num_pages,
            'prev_text' => '&laquo; Previous',
            'next_text' => 'Next &raquo;',
        ) 
    );

    return $pagination;

} 

EDIT 2

D'après vos commentaires, et comme je l'ai déjà indiqué, les pages de garde statiques et les pages simples utilisent get_query_var( 'page' ) pour la pagination, tandis que toutes les autres utilisent get_query_var( 'paged' ). J'ai mis à jour tout le code ci-dessus avec ce qui suit

if ( get_query_var('paged') ) {
    $paged = get_query_var('paged'); 
} elseif ( get_query_var('page') ) { 
    $paged = get_query_var('page'); 
} else { 
    $paged = 1; 
}

Cela réglera le problème avec page et paged et rendra votre travail de shortcode et de pagination sur toutes les pages sans aucune modification spécifique apportée.

EDIT 3

Voici une version légèrement modifiée du code par @ChipBennet qui résoudra le problème de /page/2

function home_pagination( $query = null ) 
{
    global $wp_rewrite;

    if ( get_query_var('paged') ) {
        $paged = get_query_var('paged'); 
    } elseif ( get_query_var('page') ) { 
        $paged = get_query_var('page'); 
    } else { 
        $paged = 1; 
    }


    $pagination = array(            
        'base'      => @add_query_arg( 'paged', '%#%' ),
        'format'    => '',
        'current'   => $paged,
        'total'     => $query->max_num_pages,
        'prev_text' => '&laquo; Previous',
        'next_text' => 'Next &raquo;',
    );

    if ( $wp_rewrite->using_permalinks() )
        $pagination['base'] = user_trailingslashit( trailingslashit( remove_query_arg( 's', get_pagenum_link( 1 ) ) ).'/%#%/', '' );

    if ( ! empty( $wp_query->query_vars['s'] ) )
        $pagination['add_args'] = array( 's' => get_query_var( 's' ) );

    return paginate_links( $pagination );
} 
2
Pieter Goosen

Selon le codex

Si la pagination est rompue sur une page de garde statique, vous devez ajouter le paramètre "paginé" de cette façon:

if ( get_query_var('paged') ) { $paged = get_query_var('paged'); }
elseif ( get_query_var('page') ) { $paged = get_query_var('page'); }
else { $paged = 1; }

query_posts('posts_per_page=3&paged=' . $paged); 

Le paramètre de page est remplacé par Paged, le code de la fonction de mise à jour est le suivant

public function renderPosts( $atts, $content = null ) {
    global $post;
    setup_postdata($post);

     extract( shortcode_atts( array(
            'foo' => 5, //default of 5
            'categoryslug' => 'news-views' // Currently news and views.
    ), $atts) );

    // For getting the Query variable on a statcci front page, you have
    // to use 'page' and not 'paged'. Weird.          
    $paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;


    // Two things needed: Not using the game library,
    // Definitely using the supplied slug.
    // These are two objects.

    $dontUse = get_category_by_slug('game-library');
    $catUsed = get_category_by_slug($atts->categoryslug);

    // Args for the custom query
     $query_args = array(
       'posts_per_page'   => intval($foo),
       'category__not_in' => $dontUse->term_id,
       'cat' => $catUsed->term_id,
       'paged' => $paged
     );

    $custom_query = new WP_Query($query_args);                      

            $output = '<div id="blogroll">';  
            while ( $custom_query->have_posts() ) : $custom_query->the_post();

                $output .= "<div class='home_post col span_12 clear-both'>";
                $output .=      "<div class='col span_3'><a href='" . get_the_permalink() . "'>" . get_the_post_thumbnail(get_the_ID(), 'home_post_thumb') . "</a></div>";
                $output .=      "<div class='col span_9 col_last right-Edge'>";
                $output .=        "<h2 class='home_post_header'>";
                $output .=           '<a href="' . get_the_permalink() . '">' . get_the_title() . "</a>";
                $output .=        "</h2>";
                $output .=        get_the_excerpt();
                $output .=      '<a class="home-more-link" href="' . get_the_permalink() . '"><span class="continue-reading">Read More</span></a>';
                $output .=      "</div>";
                $output .= "</div>";

            endwhile;

            wp_reset_postdata();

            // Pagination not working, but it outputs just fine?
            $output .= '<div id="pagination" class="blogroll-pagination">' . home_pagination($custom_query) . '</div></div>';
            wp_reset_query();              

            return $output;  
 }
0
Vikram Singh