I post permanenti superano i post per limite di pagina


21

Sto usando pre_get_postsper regolare il numero di post visualizzati sulla mia homepage.

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

Ma sto incontrando un problema con i post appiccicosi. Fondamentalmente, se ho post appiccicosi, la query mostrerà più dei 12 post che ho specificato, perché visualizzerà 12 più eventuali post appiccicosi. Potrei, ovviamente, ignorare i post appiccicosi:

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' );

Ma non credo sia l'ideale. Penso che i post appiccicosi debbano essere inclusi nel limite di 12 post e non aggiunti al limite. Questo è ciò che ha più senso per me. C'è un modo per raggiungere questo obiettivo? Ho fatto un errore degno del palmo della faccia?

Praticamente un duplicato di: Post e post appiccicosi per pagina ma stranamente chiusi perché troppo localizzati. Non sono d'accordo, ovviamente perché sto cercando una risposta, ma anche perché è una domanda sul perché WordPress non sembra rispettare il posts_per_page limite se stai usando post appiccicosi. Se vuoi 12 post per pagina dovresti ottenere 12, non 13, che è quello che otterrai se avessi un singolo post appiccicoso.

Risposte:


12

Ecco un approccio per tenere conto dei post permanenti ottenendo il numero di post permanenti (se presenti) e includendolo nel posts_per_pageparametro di calcolo :

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);
        }
    }
}

modificare

Nel caso in cui il numero di post per pagina che desideriamo impostare sia inferiore o uguale al numero di post appiccicosi, ne ho impostato posts_per_pageuno e ciò comporterà 13 o più post $sticky_count + 1(in questo caso) solo sul primo pagina (le pagine successive avranno 12 post). Forse è OK dato che questo caso è raro e +1 post sulla prima pagina potrebbe non essere così significativo.

Questo perché Wordpress visualizzerà tutti i post appiccicosi prima e su una pagina (la prima pagina) anche se il loro conteggio è maggiore del posts_per_pageparametro, quindi posts_per_pagein questo caso impostiamo il minimo possibile 1, poiché i 0valori negativi verranno disabilitati il posts_per_pageparametro e che farà sì che Wordpress visualizzi tutti i post sulla prima pagina.


Grande!! Penso che devi cambiare $sticky_count + (12 - $sticky_count)in 12- $sticky_countperò. Ad esempio, se ho 1 appiccicoso, allora la tua matematica continua a risolversi in 12 e quindi WP aggiunge il post appiccicoso per fare 13. Oh, e se if ($sticky_count > $posts_per_page)e impostiamo su 12, non significa che mostreremo 24+?
Helgatheviking,

@helgatheviking: hai ragione. Faccio sempre errori così sciocchi, i calcoli non sono mai stati così interessanti per me. E sì, ciò comporterebbe 24 post. Ho aggiornato il codice per tener conto di ciò e ho aggiunto un controllo per un numero di pagina. Funziona bene, ma ora ci sarà un caso in cui $posts_per_pagesarà uguale a $sticky_count, e qui ho impostato il parametro posts_per_page su 1, e penso che andrà bene dato che questo caso potrebbe essere raro e che sarà solo nella prima pagina ( $sticky_count + 1).
Ahmad M,

Grazie per la modifica! Penso che questa sia la migliore soluzione che possiamo ottenere usando post appiccicosi. Penso che potrei eventualmente ordinare in base a una semplice meta chiave se un post è in primo piano o meno. Ciò si comporta più normalmente per la mia comprensione.
Helgatheviking,

questo non riesce come soluzione se i post appiccicosi fanno parte della posts_per_page originariamente desiderata. Il numero totale di post si ridurrà, ma i post permanenti non lo faranno risalire poiché fanno parte della normale data ordinata impostata.
Andrew Killen,

3

C'è un problema se i post appiccicosi sono nella prima pagina.

La soluzione è di ridurre il conteggio dei post appiccicosi per i post appiccicosi che fanno parte della prima pagina.

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'  );

Spero che questo possa aiutare


1
Sei sicuro che non ci sia una soluzione più semplice e veloce a questo? Suggerimento: conosci la quantità di post appiccicosi e i post per pagina ...
kaiser,

Finora non ho trovato di meglio .. Questa è più una correzione per qualcosa che dovrebbe essere nel core del WP secondo me
csag

Se fosse nel core, altri scenari non funzionerebbero.
Kaiser

Questo è un bug noto e viene tracciato su core.trac.wordpress.org/ticket/27282
Will.

La soluzione di @kaiser Ahmad M non tiene conto dei post appiccicosi che sarebbero apparsi sulla prima pagina indipendentemente dal loro stato appiccicoso. Può causare la visualizzazione di un numero troppo basso di post sulla prima pagina (WordPress v4.9.7). Questa risposta è migliore perché tiene conto di ciò.
Jacob Budin,

0

Ho ripulito entrambe le risposte di cui sopra in modo da non caricare inutilmente WP_Query, correggere se la prima pagina è appiccicosa, ridurre i tempi di elaborazione delle informazioni con un codice più pulito più veloce.

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' );
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.