Lepkie posty przekraczają limit postów na stronę


21

Używam pre_get_postsdo dostosowania liczby postów wyświetlanych na mojej stronie głównej.

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

Ale mam problem z lepkimi postami. Zasadniczo, jeśli mam jakieś przyklejone posty, zapytanie wyświetli więcej niż 12 określonych przeze mnie postów, ponieważ wyświetli 12 plus wszelkie przyklejone posty. Mógłbym oczywiście zignorować przyklejone posty:

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

Ale nie sądzę, że to jest idealne. Myślę, że lepkie posty powinny być uwzględnione w limicie 12 postów, a nie dodane do limitu. To jest dla mnie najbardziej sensowne. Czy istnieje sposób na osiągnięcie tego? Czy popełniłem błąd godny twarzy?

Prawie duplikat: Przyklejone posty i posty na stronę, ale było to dziwnie zamknięte, ponieważ zbyt zlokalizowane. Nie zgadzam się, oczywiście dlatego, że szukam odpowiedzi, ale także dlatego, że wydaje się, że WordPress nie przestrzega posts_per_page limitu, jeśli używasz lepkich postów. Jeśli chcesz 12 postów na stronę, powinieneś dostać 12, a nie 13, co byś otrzymał, gdybyś miał jeden przyklejony post.

Odpowiedzi:


12

Oto podejście do rozliczania lepkich postów poprzez uzyskanie liczby lepkich postów (jeśli istnieją) i uwzględnienie ich w posts_per_pageparametrze obliczeniowym :

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

Edytować

W przypadku, gdy liczba postów na stronie, którą chcemy ustawić, jest mniejsza lub równa liczbie postów przyklejonych, ustawiłem na posts_per_pagejeden, co da 13 lub więcej postów $sticky_count + 1(w tym przypadku) tylko na pierwszym strona (kolejne strony będą miały 12 postów). Może to jest w porządku, ponieważ ten przypadek jest rzadki, a wpis +1 na pierwszej stronie może nie być tak znaczący.

Wynika to z faktu, że Wordpress wyświetli najpierw wszystkie przyklejone posty i na jednej stronie (pierwszej stronie), nawet jeśli ich liczba jest większa niż posts_per_pageparametr, dlatego posts_per_pagew tym przypadku ustawiamy minimalną możliwą liczbę 1, ponieważ, 0a ujemne wartości wyłączą posts_per_pageparametr i że będzie Wordpress, aby wyświetlić wszystkie posty na pierwszej stronie.


Świetny!! Myślę, że trzeba zmienić $sticky_count + (12 - $sticky_count), aby 12- $sticky_countchociaż. Na przykład, jeśli mam 1 lepką, to twoja matematyka nadal działa na 12, a następnie WP dodaje lepką pocztę, aby uzyskać 13. Och, a jeśli if ($sticky_count > $posts_per_page)i ustawimy na 12, czy to nie znaczy, że pokażemy 24+?
helgatheviking

@helgatheviking: masz rację. Zawsze popełniam takie głupie błędy, obliczenia nigdy nie były dla mnie tak interesujące. I tak, to dałoby 24 posty. Zaktualizowałem kod, aby to uwzględnić, i dodałem sprawdzenie numeru strony. Działa to dobrze, ale teraz będzie jeden przypadek, w którym $posts_per_pagebędzie równy $sticky_count, i tutaj ustawiam parametr posts_per_page na 1, i myślę, że będzie OK, ponieważ ten przypadek może być rzadki i będzie to tylko na pierwszej stronie ( $sticky_count + 1).
Ahmad M,

Dzięki za edycję! Myślę, że to najlepsze rozwiązanie, jakie możemy uzyskać za pomocą lepkich postów. Myślę, że w końcu mogę posortować według prostego klawisza meta, czy post jest polecany, czy nie. To działa normalnie dla mojego zrozumienia.
helgatheviking,

nie udaje się to rozwiązać, jeśli lepkie posty są częścią pierwotnie poszukiwanych post_per_page. Całkowita liczba postów zmniejszy się, ale lepkie posty nie zwiększą tej liczby, ponieważ są one częścią normalnego zestawu z zamówioną datą.
Andrew Killen,

3

Występuje problem, jeśli przyklejone posty znajdują się na pierwszej stronie.

Rozwiązaniem jest zmniejszenie liczby przyklejonych wpisów dla przyklejonych wpisów, które są częścią pierwszej strony.

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

Mam nadzieję, że to pomoże


1
Czy na pewno nie ma łatwiejszego i szybszego rozwiązania tego problemu? Podpowiedź: Znasz liczbę lepkich postów i postów na stronie ...
Kaiser

Jak dotąd nie znalazłem nic lepszego. To bardziej poprawka na coś, co powinno być w rdzeniu WP, moim zdaniem
csag

Gdyby był to rdzeń, inne scenariusze nie działałyby.
kaiser

Jest to znany błąd, który jest śledzony na core.trac.wordpress.org/ticket/27282
Will.

Rozwiązanie @kaiser Ahmad M. nie uwzględnia przyklejonych postów, które pojawiłyby się na pierwszej stronie, niezależnie od ich stanu. Może to spowodować, że na pierwszej stronie pojawi się zbyt mało postów (WordPress v4.9.7). Ta odpowiedź jest lepsza, ponieważ to wyjaśnia.
Jacob Budin

0

Oczyściłem obie powyższe odpowiedzi w jedną, aby nie ładowało niepotrzebnego WP_Query, naprawia przyklejanie na pierwszej stronie, skraca czas przetwarzania informacji przy pomocy czystszego, szybszego kodu.

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' );
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.