web-dev-qa-db-fra.com

Différent paramètre 'posts_per_page' pour le premier et reste des pages paginées?

Comment définissez-vous le paramètre de requête posts_per_page de sorte qu'un nombre différent de publications soient affichées sur la première des pages paginées (de la maison, des archives, de la recherche, etc.) et le reste?

Par exemple, disons que j'aimerais afficher 10 articles sur la première des pages paginées des archives de catégorie et 15 sur le reste. Comment fait-on ça?

Cela marche :

function itsme_category_offset( $query ) {
  if( $query->is_category() && $query->is_main_query() ) {

    if( !$query->is_paged() ) {

      $query->set( 'posts_per_page', 10 );

    } else {

      $query->set( 'offset', 10 );
      $query->set( 'posts_per_page', 15 );

    }
  }
}
add_action( 'pre_get_posts', 'itsme_category_offset' );

Mais ...

Selon l'entrée du Codex pour les paramètres de pagination WP_Query() :

offset (int) - nombre de messages à déplacer ou à passer. Avertissement: la définition du paramètre offset annule/ignore le paramètre paginé et interrompt la pagination

Et selon l’entrée liée Codex pour une solution de contournement :

La spécification de décalages codés en dur dans les requêtes peut et va rompre la pagination puisque ce dernier est utilisé en interne par WordPress pour calculer et gérer la pagination.

La solution de contournement indiquée utilise une fonction qui s'accroche dans le filtre found_posts et établit le décalage. Cela suppose que je fasse quelque chose comme ceci:

function itsme_category_offset( $query ) {
  if( $query->is_category() && $query->is_main_query() ) {
    $paged = get_query_var( 'paged' );

    if( 0 == $paged ) {

      $query->set( 'posts_per_page', 10 );

    } else {

      $offset = 10 + ( ($paged - 2) * 15 );
      $query->set( 'offset', $offset );
      $query->set( 'posts_per_page', 15 );

    }
  }
}
add_action( 'pre_get_posts', 'itsme_category_offset' );

function itsme_adjust_category_offset_pagination( $found_posts, $query ) {
  $paged = get_query_var( 'paged' );
  if( $query->is_category() && $query->is_main_query() ) {
    if( 0 == $paged ) {

      $offset = 0;

    } else {

      $offset = 10 + ( ($paged - 2) * 15 );

    }

    return $found_posts - $offset;
  }
}
add_filter( 'found_posts', 'itsme_adjust_category_offset_pagination' );

Puisque ma fonction plus simple fonctionne déjà, l’avertissement du Codex est-il toujours correct? (c.-à-d. dois-je le faire comme indiqué dans le deuxième bloc de code?) Ce problème de décalage/pagination a-t-il été résolu dans une version récente de WordPress? Et si oui: comment?

6
its_me

Cas n ° 1: décalage simple

Vous voulez "compenser" les posts d'une archive de catégorie par "n", c.-à-d. Que vous ne voulez tout simplement pas afficher les premiers/derniers posts dans une archive.

C’est-à-dire (en considérant le paramètre posts_per_page dans WP Tableau de bord> Paramètres> Lecture est défini sur 10), vous souhaitez que les publications 11 à 20 soient affichées sur la première page (par exemple example.com/category/tech/), 21 à 30 sur le second (par exemple, example.com/category/tech/page/2/), 31 à 40 sur le troisième, etc.

Quoi qu'il en soit, voici comment vous feriez cela:

/*
 * Offset posts by 10 on 'Techonology (tech)' category archive
 */
function itsme_category_offset( $query ) {
    $offset = 10;
    $ppp = get_option( 'posts_per_page' );
    $paged = $query->query_vars[ 'paged' ];

    if( $query->is_category( 'tech' ) && $query->is_main_query() ) {
        if( !is_paged() ) {

            $query->set( 'offset', $offset );

        } else {

            $paged_offset = $offset + ( ($paged - 1) * $ppp );
            $query->set( 'offset', $paged_offset );

        }
    }
}
add_action( 'pre_get_posts', 'itsme_category_offset' );

Ensuite, il y a encore une chose. Avant de créer la pagination, WordPress examine le nombre total de publications que la classe WP_Query indique avoir trouvées lors de l'exécution d'une requête.

Ainsi, pour que la pagination fonctionne correctement, vous devez supprimer la offset du nombre total de publications trouvées par la requête (car les 10 premières publications ne sont pas affichées). Et voici comment vous le feriez:

function itsme_adjust_category_offset_pagination( $found_posts, $query ) {
    $offset = 10;

    if( $query->is_category( 'tech' ) && $query->is_main_query() ) {
        return( $found_posts - $offset );
    }
}
add_filter( 'found_posts', 'itsme_adjust_category_offset_pagination', 10, 2 );

C'est tout!

PS: (Une explication plus technique peut être trouvée ici .)


Cas n ° 2: décalage conditionnel

Comme dans mon cas, vous souhaitez afficher "m" nombre de publications sur la première page d'une archive et "n" publications sur les autres.

C’est-à-dire (compte tenu du fait que vous ne souhaitez afficher que 5 articles sur la première page de l’archive et que le reste des pages adhère au paramètre posts_per_page dans WP Tableau de bord> Paramètres> Lecture, qui est réglé sur 10), vous souhaitez que les articles 1 à 5 soient affichés sur la première page (par exemple, example.com/category/tech/), 6 à 15 sur la seconde (par exemple, example.com/category/tech/page/2/), 16 à 25 sur la troisième, etc.

Voici comment vous feriez ça:

/*
 * Show a different no. of posts on the first page, and the rest
 * of the pages of 'Techonology (tech)' category archive
 */
function itsme_category_offset( $query ) {
    $ppp = get_option( 'posts_per_page' );
    $first_page_ppp = 5;
    $paged = $query->query_vars[ 'paged' ];

    if( $query->is_category( 'tech' ) && $query->is_main_query() ) {
        if( !is_paged() ) {

            $query->set( 'posts_per_page', $first_page_ppp );

        } else {

            // Not going to explain the simple math involved here
            $paged_offset = $first_page_ppp + ( ($paged - 2) * $ppp );
            $query->set( 'offset', $paged_offset );

            /*
             * As we are not adding a custom `$query->set( 'posts_per_page', ... );`,
             * the default `posts_per_page` setting from WP Dashboard > Settings > Reading
             * will be applied here.
             */

        }
    }
}
add_action( 'pre_get_posts', 'itsme_category_offset' );

Cette affaire est complexe. Donc, commençons par regarder à quoi la fonction found_posts devrait ressembler:

function itsme_adjust_category_offset_pagination( $found_posts, $query ) {
    $ppp = get_option( 'posts_per_page' );
    $first_page_ppp = 5;

    if( $query->is_category( 'tech' ) && $query->is_main_query() ) {
        if( !is_paged() ) {

            return( $found_posts );

        } else {

            return( $found_posts - ($first_page_ppp - $ppp) );

        }
    }
    return $found_posts;
}
add_filter( 'found_posts', 'itsme_adjust_category_offset_pagination', 10, 2 );

Contrairement à Cas n ° 1 , nous n’éliminons ici aucun message du total; nous devons les montrer tous; sauf que nous voulons montrer un ensemble no. des articles sur la première page des archives de la catégorie, et un autre no. des messages sur le reste des pages paginées.

Le problème est, pour calculer le no. $query (WP_Query) de pages pour générer la pagination, examine le paramètre posts_per_page pour la page en cours. Puisque nous avons défini la valeur '10' pour toutes les autres pages sauf la première, alors que sur toute autre page sauf la première, $query considère qu'il en va de même pour toutes les pages (y compris les précédentes/suivantes, y compris la première page) et commence à calculer la pagination. basé sur cela.

Ainsi, par exemple, à la 2e page (si nous prenons le nombre total de messages comme "20"), en fonction de:

  • $queryla pagination doit être: 10 + 10
  • Mais correct la pagination serait: 5 + 10 + 5 (parce que dans la fonction pre_get_posts initiale, la pagination de la première page est définie sur '5')

Donc, quand sur la 2ème page (ou n'importe quelle page sauf la première), comme dans notre exemple, nous devons faire croire à $query que le total non. des messages est de 25 pour qu'il génère une pagination correcte comme celle-ci ...

5 messages sur la 1ère page + 10 messages sur la 2ème + 5 messages sur la 3ème

... pensant que c'est en fait comme ça:

10 messages sur la 1ère page + 10 messages sur la 2ème + 5 messages sur la 3ème

Et puisque le filtre found_posts n'a aucun effet sur le nombre de publications réellement affichées sur une page donnée, nos paramètres posts_per_page de la première fonction prévalent, sans aucun problème de pagination.

Ça devrait éclaircir les choses. (Et faites-moi savoir si quelque chose ne va pas.)}


Donc, pour répondre directement à la question, vous devez toujours utiliser une fonction qui se raccorde au crochet de filtre found_posts, ajuster le $query en fonction de vos règles personnalisées et vous assurer que la pagination ne soit pas gâchée.

9
its_me

Je n'ai pas assez de points d'échange de pile pour commenter ce qui précède, mais j'ai une correction.

Cas n ° 1: Simple Offset a très bien fonctionné pour mon site. Il faut juste un correctif pour qu'il retourne le décalage par défaut lorsque la condition spéciale n'est pas remplie:

function itsme_adjust_category_offset_pagination( $found_posts, $query ) {
    $offset = 10;

    if( $query->is_category( 'tech' ) && $query->is_main_query() ) {
        return( $found_posts - $offset );
    } else {
        return $found_posts;
    }
}
add_filter( 'found_posts', 'itsme_adjust_category_offset_pagination', 10, 2 );
1
Oxfordian3