C'est une question assez intéressante ( que j'ai surévaluée, spécialement pour votre approche et vos recherches ). La grosse courbe est ici la première page de la requête:
Vous ne pouvez pas définir la requête pour renvoyer des 0
articles sur la première page
En déplaçant le contenu de chaque page d'une page vers le haut, vous perdrez la dernière page car la requête n'aura toujours que le même nombre de publications, de sorte que la $max_num_pages
propriété restera toujours la même.
Nous devrons en quelque sorte "tromper" la WP_Query
classe pour renvoyer nos messages correctement avec le décalage d'une page, et également obtenir le nombre correct de pages afin de ne pas perdre la dernière page de la requête
Regardons l'idée suivante et essayons de tout mettre en code. Avant de le faire, je voudrais cependant soulever quelques notes ici
NOTES IMPORTANTES:
Tout n'est pas testé, il pourrait donc être bogué. Assurez-vous de tester cela localement avec le débogage activé
Le code nécessite au moins PHP 5.3, toute version inférieure à 5.3 entraînera une erreur fatale. Remarque, si vous utilisez toujours une version inférieure à PHP 5.5, vous devriez déjà avoir mis à niveau il y a longtemps
Modifiez et abusez du code comme bon vous semble pour répondre à vos besoins exacts
L'IDÉE DE L'AMPOULE:
CE DONT NOUS AURONS BESOIN
Pour que tout fonctionne, nous aurons besoin des éléments suivants:
Le numéro de page en cours d'affichage
L' posts_per_page
option définie dans les paramètres de lecture
Douane offset
Modifier la $found_posts
propriété de la requête pour corriger la $max_num_pages
propriété
La pagination se WP_Query
résume à quelques lignes de code très simples
if ( empty($q['nopaging']) && !$this->is_singular ) {
$page = absint($q['paged']);
if ( !$page )
$page = 1;
// If 'offset' is provided, it takes precedence over 'paged'.
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) ) {
$q['offset'] = absint( $q['offset'] );
$pgstrt = $q['offset'] . ', ';
} else {
$pgstrt = absint( ( $page - 1 ) * $q['posts_per_page'] ) . ', ';
}
$limits = 'LIMIT ' . $pgstrt . $q['posts_per_page'];
}
Ce qui se passe essentiellement, une fois qu'un décalage est défini explicitement, le paged
paramètre est ignoré. Le premier paramètre de la LIMIT
clause SQL est recalculé à partir de l'offset et sera le nombre de publications à ignorer dans la requête SQL générée.
D'après votre question, apparemment lors de la définition offset
de 0
, la requête de décalage échoue, ce qui est étrange, car la vérification suivante doit renvoyer true
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) )
0
est un nombre valide et doit renvoyer true. Si cela ne fonctionne pas sur votre installation, vous devez déboguer le problème
Pour revenir au problème, nous allons utiliser le même type de logique pour calculer et définir notre décalage pour obtenir le post 1 à la page 2 et à partir de là paginer la requête. Pour la première page, nous ne modifierons rien, donc les articles supposés être sur la page 1 seront toujours sur la page comme d'habitude, nous aurions juste besoin de les "cacher" plus tard afin de ne pas les afficher sur la page 1
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$current_page = $q->get( 'paged' ); // Get the current page number
// We will only need to run this from page 2 onwards
if ( $current_page != 0 ) { // You can also use if ( is_paged() ) {
// Get the amount of posts per page
$posts_per_page = get_option( 'posts_per_page' );
// Recalculate our offset
$offset = ( ( $current_page - 1) * $posts_per_page ) - $posts_per_page; // This should work on page 2 where it returns 0
// Set our offset
$q->set( 'offset', $offset );
}
}
});
Vous devriez voir les mêmes messages de la page 1 à la page 2. Comme je l'ai déjà dit, si cela ne se produit pas, soit is_numeric( 0 )
renvoie false ( ce qui ne devrait pas être le cas ) ou vous avez une autre pre_get_posts
action qui essaie également de définir un décalage ou vous utilisent en utilisant les posts_*
filtres de clause ( plus précisément, le post_limits
filtre ). Ce serait quelque chose que vous auriez besoin de déboguer par vous-même.
Le prochain problème est de corriger la pagination, car comme je l'ai dit précédemment, vous aurez une page courte. Pour cela, nous devrons ajouter la valeur de get_option( 'posts_per_page' )
à la quantité de messages trouvés dans la requête car nous compensons la requête de ce montant. ce faisant, nous ajoutons effectivement 1
à la $max_num_pages
propriété.
add_action( 'found_posts', function ( $found_posts, $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$found_posts = $found_posts + get_option( 'posts_per_page');
}
}, 10, 2 );
Cela devrait tout trier, sauf la première page.
TOUS ENSEMBLE MAINTENANT ( et spécialement pour @ialocin - Yellow Submarine )
Tout cela devrait entrer dans functions.php
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$current_page = $q->get( 'paged' ); // Get the current page number
// We will only need to run this from page 2 onwards
if ( $current_page != 0 ) { // You can also use if ( is_paged() ) {
// Get the amount of posts per page
$posts_per_page = get_option( 'posts_per_page' );
// Recalculate our offset
$offset = ( ( $current_page - 1) * $posts_per_page ) - $posts_per_page; // This should work on page 2 where it returns 0
// Set our offset
$q->set( 'offset', $offset );
}
}
});
add_filter( 'found_posts', function ( $found_posts, $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$found_posts = $found_posts + get_option( 'posts_per_page');
}
return $found_posts;
}, 10, 2 );
OPTIONS DE LA PREMIÈRE PAGE
Il y a quelques options ici:
OPTION 1
J'irais très probablement pour cette option. Ce que vous voudriez faire ici, c'est créer un category-news.php
( si vous ne l'avez pas encore fait ). Ce sera le modèle qui sera utilisé chaque fois que la news
catégorie sera consultée. Ce modèle sera très simple
Exemple
<?php
get_header()
if ( !is_paged() ) { // This is the first page
get_template_part( 'news', 'special' );
} else { // This is not the first page
get_template_part( 'news', 'loop' );
}
get_sidebar();
get_footer();
Comme vous pouvez le voir, j'ai inclus deux parties de modèle, news-special.php
et news-loop.php
. Maintenant, les bases des deux modèles personnalisés sont:
news-special.php
-> Cette partie du modèle sera tout ce que vous souhaitez afficher sur la première page. Ajoutez toutes vos informations statiques personnalisées ici. Soyez très prudent de ne pas appeler la boucle dans ce modèle car cela afficherait les messages de la première page.
news-loop.php
-> C'est le modèle où nous invoquerons la boucle. Cette section ressemblera à ceci:
global $wp_query;
while ( have_posts() ) {
the_post();
// Your template tags and markup
}
OPTION 2
Créez un modèle séparé avec votre contenu statique et utilisez simplement le category_template
filtre pour utiliser ce modèle lorsque nous affichons la première page de la news
catégorie. Veillez également à ne pas invoquer la boucle par défaut dans ce modèle. Assurez-vous également que votre convention de dénomination ici n'entre pas en collision avec les noms de modèle dans la hiérarchie des modèles
J'espère que c'est utile. N'hésitez pas à laisser des commentaires avec inquiétudes
ÉDITER
Grâce à l'OP, il y a un bug certain dans la WP_Query
classe, vérifiez le ticket trac # 34060 . Le code que j'ai publié provient de Wordpress v4.4, et le bug est corrigé dans cette version.
Je suis retourné au code source de la v4.3, où se trouve le bogue, et je peux confirmer qu'il 0
est ignoré lorsqu'il est défini comme valeur offset
car le code vérifie simplement si le offset
paramètre est empty
. 0
est considéré comme vide en PHP. Je ne sais pas si ce comportement (bogue) ne se trouve que dans la v4.3 uniquement ou dans toutes les versions précédentes (selon le ticket, ce bogue est dans la v4.3), mais il existe un correctif pour ce bogue que vous pouvez vérifier dans le ticket trac. Comme je l'ai dit, ce bug a définitivement été corrigé dans la v4.4
return $found_posts;
après l'instruction if dans l'action found_posts. Merci!