Bài viết dính vượt quá bài viết trên mỗi trang giới hạn


21

Tôi đang sử dụng pre_get_postsđể điều chỉnh số lượng bài đăng được hiển thị trên trang chủ của mình.

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

Nhưng tôi đang gặp vấn đề với bài viết dính. Về cơ bản, nếu tôi có bất kỳ bài đăng dính nào, truy vấn sẽ hiển thị nhiều hơn 12 bài đăng tôi đã chỉ định, bởi vì nó sẽ hiển thị 12 bài cộng với bất kỳ bài đăng dính nào. Tất nhiên, tôi có thể bỏ qua các bài viết dính:

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

Nhưng tôi không nghĩ rằng điều này là lý tưởng. Tôi nghĩ rằng các bài viết dính nên được bao gồm trong giới hạn của 12 bài viết, và không được thêm vào giới hạn. Đó là những gì có ý nghĩa nhất đối với tôi. Có cách nào để đạt được điều đó? Tôi đã thực hiện một lỗi đáng mặt?

Khá nhiều bản sao của: Bài viết dính & Bài viết trên mỗi trang nhưng đã bị đóng một cách kỳ lạ vì quá cục bộ. Tôi không đồng ý, rõ ràng vì tôi đang tìm kiếm một câu trả lời, nhưng cũng vì đó là câu hỏi tại sao WordPress dường như không tôn trọng posts_per_page giới hạn nếu bạn đang sử dụng các bài đăng dính. Nếu bạn muốn 12 bài đăng trên mỗi trang, bạn sẽ nhận được 12, không phải 13, đó là những gì bạn sẽ nhận được nếu bạn có một bài đăng dính.

Câu trả lời:


12

Đây là một cách tiếp cận để giải thích cho các bài viết dính bằng cách lấy số lượng bài viết dính (nếu có) và đưa nó vào posts_per_pagetham số tính toán :

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

Chỉnh sửa

Trong trường hợp số lượng bài đăng trên mỗi trang chúng tôi muốn đặt ít hơn hoặc bằng số lượng bài đăng dính, tôi đã đặt thành posts_per_pagemột bài và điều đó sẽ dẫn đến 13 bài đăng trở lên $sticky_count + 1(trong trường hợp này) chỉ ở lần đầu tiên trang (các trang tiếp theo sẽ có 12 bài viết). Có lẽ điều đó là ổn vì trường hợp này là hiếm và +1 bài đăng trên trang đầu tiên có thể không đáng kể.

Điều này là do Wordpress sẽ hiển thị tất cả các bài đăng dính trước và trên một trang (trang đầu tiên) ngay cả khi số lượng của chúng lớn hơn posts_per_pagetham số, vì vậy chúng tôi đặt posts_per_pagetrong trường hợp này là số lượng tối thiểu có thể 1, bởi vì 0và các giá trị âm sẽ vô hiệu hóa các posts_per_pagetham số và điều đó sẽ làm cho Wordpress để hiển thị tất cả các bài viết trên trang đầu tiên.


Tuyệt quá!! Tôi nghĩ rằng bạn cần phải thay đổi $sticky_count + (12 - $sticky_count)để 12- $sticky_countmặc dù. Ví dụ: nếu tôi có 1 dính, thì toán của bạn vẫn hoạt động đến 12, và sau đó WP thêm bài dính để thực hiện 13. Ồ, và nếu if ($sticky_count > $posts_per_page)và chúng tôi đặt thành 12, điều đó có nghĩa là chúng tôi sẽ hiển thị 24+ chứ?
đạp xe

@helgatheviking: bạn nói đúng. Tôi luôn mắc phải những sai lầm ngớ ngẩn như vậy, tính toán chưa bao giờ thú vị với tôi như vậy. Và vâng, điều đó sẽ dẫn đến 24 bài viết. Tôi đã cập nhật mã để giải thích cho điều đó và tôi đã thêm một kiểm tra cho số trang. Điều này hoạt động tốt, nhưng bây giờ sẽ có một trường hợp $posts_per_pagesẽ bằng $sticky_countvà ở đây tôi đặt tham số tests_per_page là 1, và tôi nghĩ rằng sẽ ổn vì trường hợp này có thể hiếm gặp và điều đó sẽ chỉ trên trang đầu tiên ( $sticky_count + 1).
Ahmad M

Cảm ơn đã chỉnh sửa! Tôi nghĩ rằng đây là giải pháp tốt nhất chúng ta có thể nhận được bằng cách sử dụng bài viết dính. Tôi nghĩ rằng cuối cùng tôi có thể sắp xếp theo một khóa meta đơn giản cho dù bài đăng có nổi bật hay không. Điều đó hành xử bình thường hơn cho sự hiểu biết của tôi.
đạp xe

đây là một giải pháp nếu bài viết dính là một phần của bài viết mong muốn ban đầu. Tổng số bài viết sẽ giảm nhưng các bài đăng dính sẽ không đẩy số đó trở lại vì chúng là một phần của ngày đặt hàng bình thường.
Andrew Killen

3

Có một vấn đề nếu các bài viết dính ở trang đầu tiên.

Giải pháp là giảm số lượng bài đăng dính cho các bài đăng dính là một phần của trang đầu tiên.

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

tôi mong nó sẽ có ích


1
Bạn có chắc chắn không có giải pháp nào dễ dàng và nhanh chóng hơn cho vấn đề đó không? Gợi ý: Bạn biết số lượng bài đăng dính và bài đăng trên mỗi trang ...
kaiser

Tôi đã không tìm thấy tốt hơn cho đến nay .. Đây là một sửa chữa cho một cái gì đó nên có trong lõi WP theo ý kiến ​​của tôi
csag

Nếu nó là cốt lõi, các kịch bản khác sẽ không hoạt động.
kaiser

Đây là một lỗi đã biết và đang được theo dõi tại core.trac.wordpress.org/ticket/27282
Will.

@kaiser Giải pháp của Ahmad M không giải thích cho các bài đăng dính sẽ xuất hiện trên trang đầu tiên bất kể trạng thái dính của chúng. Nó có thể dẫn đến quá ít bài đăng xuất hiện trên trang đầu tiên (WordPress v4.9.7). Câu trả lời này là tốt hơn bởi vì nó chiếm cho điều đó.
Jacob Budin

0

Tôi đã dọn sạch cả hai câu trả lời trên thành một để nó không tải WP_Query không cần thiết, sửa lỗi nếu dính trên trang đầu tiên, giảm thời gian xử lý thông tin bằng mã nhanh hơn.

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' );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.