Les messages collants dépassent la limite de messages par page

21

J'utilise pre_get_postspour ajuster le nombre de messages affichés sur ma page d'accueil.

function lifelounge_query_adjust( $query ) {
    if ( is_home() ) {
        set_query_var( 'posts_per_page', 12 );
        return;
    }
}
add_filter( 'pre_get_posts', 'lifelounge_query_adjust' );

Mais je rencontre un problème avec les messages collants. Fondamentalement, si j'ai des messages collants, la requête affichera plus que les 12 messages que j'ai spécifiés, car elle affichera 12 plus tous les messages collants. Je pourrais, bien sûr, ignorer les messages collants:

function lifelounge_query_adjust( $query ) {
    if ( is_home() ) {
        set_query_var( 'posts_per_page', 1 );
        set_query_var( 'ignore_sticky_posts', 1 );
        return;
    }
}
add_filter( 'pre_get_posts', 'lifelounge_query_adjust' );

Mais je ne pense pas que ce soit idéal. Je pense que les messages collants devraient être inclus dans la limite de 12 messages, et non ajoutés à la limite. C'est ce qui me semble le plus logique. Y a-t-il un moyen d'y parvenir? Ai-je fait une erreur digne du visage?

Quasiment un doublon de: Post-it collants & Post par page mais qui était étrangement fermé car trop localisé. Je ne suis pas d'accord, évidemment parce que je cherche une réponse, mais aussi parce que c'est une question de savoir pourquoi WordPress ne semble pas respecter la posts_per_page limite si vous utilisez des posts collants. Si vous voulez 12 articles par page, vous devez en obtenir 12, et non 13, ce que vous obtiendriez si vous aviez un seul article collant.

helgatheviking
la source

Réponses:

12

Voici une approche pour prendre en compte les messages collants en obtenant le nombre de messages collants (le cas échéant) et en l'incluant dans le posts_per_pageparamètre de calcul :

add_action('pre_get_posts', 'ad_custom_query');
function ad_custom_query($query) {

    if ($query->is_main_query() && is_home()) {

        // set the number of posts per page
        $posts_per_page = 12;
        // get sticky posts array
        $sticky_posts = get_option( 'sticky_posts' );

        // if we have any sticky posts and we are at the first page
        if (is_array($sticky_posts) && !$query->is_paged()) {

            // counnt the number of sticky posts
            $sticky_count = count($sticky_posts);

            // and if the number of sticky posts is less than
            // the number we want to set:
            if ($sticky_count < $posts_per_page) {
                $query->set('posts_per_page', $posts_per_page - $sticky_count);

            // if the number of sticky posts is greater than or equal
            // the number of pages we want to set:
            } else {
                $query->set('posts_per_page', 1);
            }

        // fallback in case we have no sticky posts
        // and we are not on the first page
        } else {
            $query->set('posts_per_page', $posts_per_page);
        }
    }
}

modifier

Dans le cas où le nombre de messages par page que nous souhaitons définir est inférieur ou égal au nombre de messages collants, j'ai défini le posts_per_pageà un et cela se traduira par 13 messages ou plus $sticky_count + 1(dans ce cas) uniquement sur le premier page (les pages suivantes auront 12 messages). Peut-être que c'est OK car ce cas est rare et +1 post sur la première page peut ne pas être si important.

En effet, Wordpress affichera tous les articles collants en premier et sur une seule page (la première page) même si leur nombre est supérieur au posts_per_pageparamètre.Nous définissons donc posts_per_pagedans ce cas la quantité minimale possible 1, car 0les valeurs négatives désactiveront le posts_per_pageparamètre et cela fera Wordpress pour afficher tous les messages sur la première page.

Ahmad M
la source
Génial!! Je pense que vous avez besoin de changer $sticky_count + (12 - $sticky_count)pour 12- $sticky_countbien. Par exemple, si j'ai 1 collant, alors vos calculs fonctionnent toujours à 12, puis WP ajoute le post collant pour en faire 13. Oh, et si if ($sticky_count > $posts_per_page)et nous avons réglé à 12, cela ne veut-il pas dire que nous afficherons 24+?
helgatheviking
@helgatheviking: vous avez raison. Je fais toujours des erreurs aussi stupides, les calculs n'ont jamais été aussi intéressants pour moi. Et oui, cela se traduirait par 24 postes. J'ai mis à jour le code pour en tenir compte et j'ai ajouté une vérification pour un numéro de page. Cela fonctionne bien, mais maintenant il y aura un cas où $posts_per_pagesera égal à $sticky_count, et ici je règle le paramètre posts_per_page à 1, et que je pense que ce sera OK car ce cas peut être rare et ce ne sera que sur la première page ( $sticky_count + 1).
Ahmad M
Merci pour l'édition! Je pense que c'est la meilleure solution que nous pouvons obtenir en utilisant des messages collants. Je pense que je pourrais éventuellement trier par une simple méta-clé pour savoir si un message est en vedette ou non. Cela se comporte plus normalement pour ma compréhension.
helgatheviking
cela échoue comme solution si les messages collants font partie de la posts_per_page initialement recherchée. Le nombre total de publications diminuera, mais les publications collantes ne repousseront pas ce nombre car elles font partie de l'ensemble de dates normal ordonné.
Andrew Killen
3

Il y a un problème si les messages collants sont dans la première page.

La solution consiste à décrémenter le nombre de messages collants pour les messages collants qui font partie de la première page.

function fix_posts_per_page_with_sticky_posts( $query ) {

    if ( $query->is_main_query() ) {

        // set the number of posts per page
        $posts_per_page = 12;

        // get sticky posts array
        $sticky_posts = get_option( 'sticky_posts' );

        // get queried post ids array
        $ids = array();
        $args = array(
            'post_type' => 'post',
            'post_per_page' => $posts_per_page,
            'paged' => 1
        );

        $posts = get_posts( $args );

        foreach ( $posts as $post ) {
            $ids[] = $post->ID;
        }

        // if we have any sticky posts and we are at the first page
        if ( is_array( $sticky_posts ) && ! $query->is_paged() ) {

            // count the number of sticky posts
            $sticky_count = count( $sticky_posts );

            foreach ( $sticky_posts as $sticky_post ) {
                if ( in_array( $sticky_post, $ids ) ) {
                    // decrement sticky posts count if the sticky post in on the page
                    $sticky_count--;
                }
            }

            // and if the number of sticky posts is less than
            // the number we want to set:
            if ( $sticky_count < $posts_per_page ) {
                $query->set( 'posts_per_page', $posts_per_page - $sticky_count );

            // if the number of sticky posts is greater than or equal
            // the number of pages we want to set:
            } else {
                $query->set( 'posts_per_page', 1 );
            }

        // fallback in case we have no sticky posts
        // and we are not on the first page
        } else {
            $query->set( 'posts_per_page', $posts_per_page );
        }
    }
}
add_action( 'pre_get_posts', 'fix_posts_per_page_with_sticky_posts'  );

J'espère que cela aidera

csag
la source
1
Êtes-vous sûr qu'il n'y a pas de solution plus simple et plus rapide à cela? Astuce: Vous connaissez la quantité de messages collants et les messages par page ...
kaiser
Je n'ai pas trouvé mieux jusqu'à présent .. C'est plus un correctif pour quelque chose qui devrait être dans le noyau WP à mon avis
csag
Si c'était au cœur, d'autres scénarios ne fonctionneraient pas.
kaiser
Il s'agit d'un bogue connu et suivi sur core.trac.wordpress.org/ticket/27282
Will.
La solution de @kaiser Ahmad M ne prend pas en compte les messages collants qui seraient apparus sur la première page indépendamment de leur état collant. Il peut en résulter trop peu de publications sur la première page (WordPress v4.9.7). Cette réponse est meilleure car elle explique cela.
Jacob Budin
0

J'ai nettoyé les deux réponses ci-dessus en une seule afin qu'elle ne charge pas WP_Query inutile, corrige si le collant sur la première page, réduit le temps de traiter les informations avec un code plus rapide et plus propre.

function modify_main_query( $query ) {
   if ( ( $query->is_home() || is_front_page() ) && $query->is_main_query() ) {
         // set the number of posts per page
        $posts_per_page = 12;
        // get sticky posts array
        $sticky_posts = get_option( 'sticky_posts' );
        // if we have any sticky posts and we are at the first page
        if (is_array($sticky_posts) && !$query->is_paged()) {
            // make a second query to make sure the sticky posts will still work 
            // correctly when on the first page
            // Only reply with the ID's as that is all that is needed
            $args = [
                'post_type' => 'post',
                'post_per_page' => $posts_per_page,
                'paged' => 1,
                'fields' => 'ids'
            ];
            // Array flip to reduce the time taken by 
            // using isset and not in_array
            $posts = array_flip( get_posts( $args ) );

            // count the number of sticky posts
            $sticky_count = count($sticky_posts);

            // loop the posts from the 2nd query to see if the ID's of the sticky posts
            // sit inside it.
            foreach ( $sticky_posts as $sticky_post ) {
                if(isset($posts[$sticky_post])){
                    $sticky_count--;
                }
            }
            // and if the number of sticky posts is less than
            // the number we want to set:
            if ($sticky_count < $posts_per_page) {
               $query->set('posts_per_page', $posts_per_page - $sticky_count);
            } else {
                // if the number of sticky posts is greater than or equal
                // the number of pages we want to set:
                $query->set('posts_per_page', 1);
            }
        // fallback in case we have no sticky posts
        // and we are not on the first page
        } else {
            $query->set('posts_per_page', $posts_per_page);
        }
    } 
}

add_action( "pre_get_posts", 'modify_main_query' );
Andrew Killen
la source