web-dev-qa-db-fra.com

Deux boucles personnalisées, pagination, offset

J'ai deux boucles utilisant WP_Query.

La première boucle montre X posts. Pas de pagination.
( boucle A )

La deuxième boucle montre Y posts. Avec pagination personnalisée.
( boucle B )

Ça marche un peu; mais vous pouvez voir la seconde boucle répéter X posts depuis la première boucle. La première chose qui me vient à l’esprit est de définir un décalage (égal à X), mais cela rompt la pagination et une page entière du Codex est consacrée à cette question. Il existe également une solution de contournement, mais le problème étant que j’ai deux boucles, cette solution de contournement s’applique aux deux.

La question est donc
Comment est-ce que je fais ce travail comme prévu?
Une solution possible consisterait à transformer le code du Codex en "cible" la deuxième boucle, mais je ne suis pas un programmeur et je ne sais pas comment faire cela. Peut-être y a-t-il même un meilleur moyen de réaliser ce que j'essaie de faire, mais je ne peux penser à aucune autre option.

Information additionnelle
1) Je ne peux pas utiliser une seule boucle à cause de la complexité de mon balisage.
2) Tout le code a été trouvé sur le net
3) Les deux boucles ne sont pas restreintes par les auteurs, les catégories ou quoi que ce soit. Il s'agit toujours du même contenu avec deux mises en page différentes "combinées" pour ressembler à un "flux" unique.

et comme je ne peux pas poster plus de 2 liens, voici le code de pagination

function custom_pagination($numpages = '', $pagerange = '', $paged='') {
    if (empty($pagerange)) {
        $pagerange = 2;
    }

/**
    This first part of our function is a fallback
    for custom pagination inside a regular loop that
    uses the global $paged and global $wp_query variables.

    It's good because we can now override default pagination
    in our theme, and use this function in default quries
    and custom queries.
**/

global $paged;
if (empty($paged)) {
    $paged = 1;
}
if ($numpages == '') {
    global $wp_query;
    $numpages = $wp_query->max_num_pages;
    if(!$numpages) {
        $numpages = 1;
    }
}

/** 
    We construct the pagination arguments to enter into our paginate_links
    function. 
**/

$pagination_args = array(
    'base'            => get_pagenum_link(1) . '%_%',
    'format'          => 'page/%#%',
    'total'           => $numpages,
    'current'         => $paged,
    'show_all'        => False,
    'end_size'        => 1,
    'mid_size'        => $pagerange,
    'prev_next'       => True,
    'prev_text'       => __('«'),
    'next_text'       => __('»'),
    'type'            => 'plain',
    'add_args'        => false,
    'add_fragment'    => ''
);

$paginate_links = paginate_links($pagination_args);

if ($paginate_links) {
    echo "<nav class='custom-pagination'>";
        echo "<span class='page-numbers page-num'>Page " . $paged . " of " . $numpages . "</span> ";
        echo $paginate_links;
    echo "</nav>";
}
}

solution du Codex

add_action('pre_get_posts', 'myprefix_query_offset', 1 );
function myprefix_query_offset(&$query) {

//Before anything else, make sure this is the right query...
if ( ! $query->is_home() ) {
    return;
}

//First, define your desired offset...
$offset = 1;

//Next, determine how many posts per page you want (we'll use WordPress's settings)
$ppp = get_option('posts_per_page');

//Next, detect and handle pagination...
if ( $query->is_paged ) {

    //Manually determine page query offset (offset + current page (minus one) x posts per page)
    $page_offset = $offset + ( ($query->query_vars['paged']-1) * $ppp );

    //Apply adjust page offset
    $query->set('offset', $page_offset );

}
else {

    //This is the first page. Just use the offset...
    $query->set('offset',$offset);

}
}


add_filter('found_posts', 'myprefix_adjust_offset_pagination', 1, 2 );
function myprefix_adjust_offset_pagination($found_posts, $query) {

//Define our offset again...
$offset = 1;

//Ensure we're modifying the right query object...
if ( $query->is_home() ) {
    //Reduce WordPress's found_posts count by the offset... 
    return $found_posts - $offset;
}
return $found_posts;
}
1
Colton

_ {Je ne peux pas utiliser une seule boucle à cause de la complexité de mon balisage.}

Le balisage, aussi complexe soit-il, ne devrait jamais être une base valable pour décider d'exécuter plusieurs boucles. Plusieurs boucles ne doivent être utilisées que s’il n’ya absolument aucun autre moyen d’obtenir un résultat donné, ce qui est presque toujours le cas lorsque différents résultats sont nécessaires par argument de requête, comme des publications différentes par page et par type d’article.

Les deux boucles ne sont pas restreintes par les auteurs, les catégories ou quoi que ce soit

L'instruction ci-dessus ne valide pas non plus l'utilisation d'une deuxième boucle. Sur la base de cette déclaration, nous n’aurions besoin que d’une boucle, quel que soit le degré de complexité de votre balisage.

Le mode d'affichage des résultats d'une requête spécifique peut toujours être manipulé de la manière suivante:

  • rewind_posts() qui vous permet de relancer la boucle une seconde, troisième ou centième fois selon vos besoins

  • des compteurs personnalisés ou le compteur de boucles intégré qui compte les publications et vous permet de faire quelque chose de différent si le compteur de boucles/compteur personnalisé atteint un nombre spécifique

  • balises/instructions conditionnelles permettant de cibler des publications spécifiques en fonction de conditions spécifiques, par exemple le type ou la catégorie de publication

  • des filtres comme le the_posts qui vous permet de modifier le tableau des messages renvoyés, notamment l'ajout/la suppression et/ou la réorganisation de messages

  • les fonctions normales de PHP telles que usort(), qui peuvent être utilisées pour trier le tableau retourné avant de les afficher à l'écran

  • nous pouvons toujours manipuler la requête principale avec pre_get_posts pour afficher ce que nous voulons

Ce ne sont que quelques options que vous pouvez utiliser au lieu d’exécuter plusieurs boucles. Le problème avec plusieurs boucles sont

  • ils permettent permet problématique en matière de pagination

  • provoque des requêtes inutiles dans la base de données, ce qui ralentit les temps de chargement des pages et gaspille des ressources

Vous devez toujours vous rappeler que vous ne devez jamais remplacer la boucle principale qui affiche les résultats de la requête principale par une requête personnalisée. Ils mènent toujours à plus de problèmes que de les résoudre. Vous devriez prendre votre temps et lire le post suivant:

Pour résoudre votre problème, vous pouvez supprimer votre action pre_get_posts et le filtre found_posts car vous n'avez pas besoin de définir de décalage ni de recalculer la pagination.

Vous devrez ajuster votre boucle sur la page souhaitée en fonction de vos besoins.

EXEMPLE 1

Styling le premier post différent et affiche plus d'informations que d'autres posts

if ( have_posts() ) {
    while ( have_posts() ) {
        the_post();

            if ( 0 === $wp_query->current_post ) { // Target the first post only
                // Do what you need to do for the first post only
            } else {
                // Display all the other posts as needed   
            }
    }
}

OU

if ( have_posts() ) {
    // Start our custom counter
    $counter = 0;
    while ( have_posts() ) {
        the_post();

            if ( 0 === $counter ) { // Target the first post only
                // Do what you need to do for the first post only
            } else {
                // Display all the other posts as needed   
            }
        // Update the counter 
       $counter++;
    }
}

Vous pouvez appliquer cette méthode à n’importe quel balisage complexe. Vous pouvez définir des compteurs personnalisés pour ouvrir et fermer des divs personnalisés, appliquer un style différent pour publier la position ou même créer des grilles de publication. J'ai écrit pas mal de posts sur ce sujet, alors assurez-vous de chercher dans mes réponses

Exemple 2

Si vous devez afficher les articles groupés par type d’article avec les types d’article post et page. Ici, nous allons exécuter la boucle pour afficher les articles du type de poste post, rembobiner la boucle et l'exécuter à nouveau, mais cette fois-ci n'afficher que les articles de type page

if ( have_posts() ) {
    while ( have_posts() ) {
        the_post();

            if ( 'post' === get_post_type() ) { // Only display posts from post post type
                // Do what you need to do post post type posts
            } 
    }

    rewind_posts(); // Rewind the loop so we can run it again

    while ( have_posts() ) {
        the_post();

            if ( 'page' === get_post_type() ) { // Only display posts from page post type
                // Do what you need to do page post type posts
            } 
    }
}

CONCLUSION

Donc, comme vous le voyez, quelle que soit la complexité de votre notation, cela ne valide pas toujours la nécessité de boucles multiples, une boucle suffira toujours, nous devons simplement utiliser la boucle, PHP et filtre intelligemment à notre avantage

2
Pieter Goosen