Клейкі пости перевищують кількість дописів на сторінку


21

Я використовую pre_get_postsдля регулювання кількості публікацій, які відображаються на моїй домашній сторінці.

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

Але у мене виникають проблеми з липкими повідомленнями. В основному, якщо у мене є якісь клейкі повідомлення, запит відображатиме більше 12 вказаних мною публікацій, оскільки він відображатиме 12 плюс будь-які липкі повідомлення. Я, звичайно, міг ігнорувати липкі повідомлення:

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

Але я не думаю, що це ідеально. Я думаю, що клейкі пости повинні бути включені в ліміт 12 дописів, а не додаватися до ліміту. Саме це має для мене найбільше сенсу. Чи є спосіб досягти цього? Чи зробив я помилку, гідну обличчя?

Дуже багато дубліката: Клейкі повідомлення та повідомлення на сторінку, але це було дивно закрито як занадто локалізоване. Я не погоджуюся, очевидно, тому що я шукаю відповідь, а також тому, що це питання, чому WordPress, здається, не дотримується posts_per_page межі, якщо ви використовуєте клейкі повідомлення. Якщо ви хочете 12 повідомлень на сторінці, ви повинні отримати 12, а не 13, це те, що ви отримали, якби у вас було одне липке повідомлення.

Відповіді:


12

Ось підхід до обліку липких публікацій, отримавши кількість липких публікацій (якщо такі є) та включіть їх у posts_per_pageпараметр обчислення :

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

Редагувати

У тому випадку, коли кількість публікацій на сторінці, яку ми хочемо встановити, менша або дорівнює кількості клейких дописів, я встановив posts_per_pageодин, і це призведе до 13 і більше публікацій $sticky_count + 1(у цьому випадку) лише на першій сторінка (наступні сторінки матимуть 12 повідомлень). Можливо, це нормально, оскільки цей випадок рідкісний, і публікація +1 на першій сторінці може бути не такою істотною.

Це тому, що Wordpress відображатиме всі липкі повідомлення першими та на одній сторінці (перша сторінка), навіть якщо їх кількість перевищує posts_per_pageпараметр, тому ми встановлюємо posts_per_pageв цьому випадку мінімально можливий обсяг, який є 1, оскільки 0негативні значення будуть відключені posts_per_pageпараметр і що буде робити Wordpress , щоб відобразити всі повідомлення на першій сторінці.


Чудово !! Я думаю , що потрібно змінити , $sticky_count + (12 - $sticky_count)щоб 12- $sticky_countхоча. Наприклад, якщо у мене є 1 липкий, то ваша математика все одно працює до 12, а потім WP додає клейкий пост, щоб зробити 13. О, а якщо if ($sticky_count > $posts_per_page)і ми встановимо 12, чи не це означає, що ми покажемо 24+?
helgatheviking

@helgatheviking: ти маєш рацію. Я завжди роблю такі дурні помилки, розрахунки мені ніколи не були такі цікаві. І так, це призвело б до 24 публікацій. Я оновив код, щоб врахувати це, і додав чек на номер сторінки. Це добре працює, але тепер буде один випадок, коли $posts_per_pageбуде дорівнювати $sticky_count, і тут я встановив параметр posts_per_page рівним 1, і я думаю, що це буде нормально, оскільки цей випадок може бути рідкісним, і це буде лише на першій сторінці ( $sticky_count + 1).
Ахмад М

Дякуємо за редагування! Я думаю, що це найкраще рішення, яке ми можемо отримати, використовуючи клейкі пости. Я думаю, що я можу врешті-решт сортувати за допомогою простого мета-ключа щодо того, розміщена посада чи ні. Для мого розуміння це поводиться нормальніше.
helgatheviking

це не вдається як рішення, якщо клейкі дописи є частиною спочатку шуканої сторінки_пер_сторінки. Загальна кількість публікацій зменшиться, але клейкі пости не підштовхнуть це число назад, оскільки вони є частиною звичайного набору встановлених дат.
Ендрю Кіллен

3

Виникає проблема, якщо клейкі дописи є на першій сторінці.

Рішення полягає в зменшенні кількості клейких постів для клейких постів, що входять до першої сторінки.

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

Сподіваюся, це допоможе


1
Ви впевнені, що немає простішого та швидшого вирішення цього питання? Підказка: Ви знаєте кількість клейких дописів та дописів на сторінку ...
kaiser

Поки що я не знайшов кращого .. Це більше виправлення того, що має бути в ядрі WP, на мій погляд
csag

Якби це було в основі, інші сценарії не працювали б.
кайзер

Це відома помилка і її відслідковують у core.trac.wordpress.org/ticket/27282
Буде.

Рішення @kaiser Ahmad M не враховує липких публікацій, які з’являться на першій сторінці незалежно від їх липкого стану. Це може призвести до того, що на першій сторінці з’явиться занадто мало публікацій (WordPress v4.9.7). Ця відповідь краща, оскільки вона пояснює це.
Яків Будін

0

Я очистив обидві вищевказані відповіді в одну, щоб вона не завантажувала зайвих WP_Query, виправляє, якщо липкий на першій сторінці, скорочує час на обробку інформації з більш швидким кодом.

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' );
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.