Las publicaciones fijas exceden las publicaciones por límite de página

21

Estoy usando pre_get_postspara ajustar la cantidad de publicaciones que se muestran en mi página de inicio.

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

Pero me encuentro con un problema con las publicaciones adhesivas. Básicamente, si tengo publicaciones fijas, la consulta mostrará más de las 12 publicaciones que he especificado, porque mostrará 12 más cualquier publicación fija. Podría, por supuesto, ignorar las publicaciones adhesivas:

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

Pero no creo que esto sea ideal. Creo que las publicaciones fijas deberían incluirse en el límite de 12 publicaciones y no agregarse al límite. Eso es lo que tiene más sentido para mí. ¿Hay alguna manera de lograr eso? ¿He cometido un error digno de palmarse la cara?

Prácticamente un duplicado de: Publicaciones fijas y Publicaciones por página, pero eso estaba extrañamente cerrado porque estaba demasiado localizado. No estoy de acuerdo, obviamente porque estoy buscando una respuesta, pero también porque es una cuestión de por qué WordPress no parece respetar el posts_per_page límite si está utilizando publicaciones fijas. Si desea 12 publicaciones por página, debe obtener 12, no 13, que es lo que obtendría si tuviera una sola publicación adhesiva.

helgatheviking
fuente

Respuestas:

12

Aquí hay un enfoque para tener en cuenta las publicaciones fijas al obtener el número de publicaciones fijas (si las hay) e incluirlas en el posts_per_pageparámetro de cálculo :

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

Editar

En el caso en el que el número de publicaciones por página que deseamos establecer es menor o igual que el número de publicaciones fijas, he configurado el posts_per_pagea una y eso dará como resultado 13 o más publicaciones $sticky_count + 1(en este caso) solo en la primera página (las páginas siguientes tendrán 12 publicaciones). Tal vez eso esté bien ya que este caso es raro y la publicación de +1 en la primera página puede no ser tan significativa.

Esto se debe a que Wordpress mostrará todas las publicaciones adhesivas primero y en una página (la primera página) incluso si su recuento es mayor que el posts_per_pageparámetro, por lo que establecemos posts_per_pageen este caso la cantidad mínima posible, que es 1, porque 0los valores negativos se deshabilitarán el posts_per_pageparámetro y eso hará que Wordpress muestre todas las publicaciones en la primera página.

Ahmad M
fuente
¡¡Excelente!! Creo que se necesita para cambiar $sticky_count + (12 - $sticky_count)al 12- $sticky_countembargo. Por ejemplo, si tengo 1 adhesivo, entonces tu matemática aún funciona a 12, y luego WP agrega la publicación adhesiva para hacer 13. Ah, y si if ($sticky_count > $posts_per_page)lo establecemos en 12, ¿eso no significa que mostraremos 24+?
helgatheviking
@helgatheviking: tienes razón. Siempre cometo errores tan tontos, los cálculos nunca fueron tan interesantes para mí. Y sí, eso daría como resultado 24 publicaciones. He actualizado el código para dar cuenta de eso, y agregué un cheque para un número de página. Esto funciona bien, pero ahora habrá un caso en el $posts_per_pageque será igual a $sticky_count, y aquí configuro el parámetro posts_per_page en 1, y creo que estará bien, ya que este caso puede ser raro y solo será en la primera página ( $sticky_count + 1)
Ahmad M
Gracias por la edición! Creo que esta es la mejor solución que podemos obtener usando publicaciones fijas. Creo que eventualmente podría ordenar por una simple meta clave para ver si una publicación aparece o no. Eso se comporta más normalmente para mi comprensión.
helgatheviking
esto falla como una solución si las publicaciones fijas son parte de posts_per_page originalmente deseados. El número total de publicaciones se reducirá, pero las publicaciones fijas no harán que ese número vuelva a subir, ya que son parte del conjunto ordenado de fecha normal.
Andrew Killen
3

Hay un problema si las publicaciones adhesivas están en la primera página.

La solución es disminuir el recuento de publicaciones fijas para las publicaciones fijas que forman parte de la primera página.

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

Espero que ayude

csag
fuente
1
¿Estás seguro de que no hay una solución más fácil y rápida para eso? Insinuación: Usted sabe la cantidad de mensajes pegajosas y los mensajes por la página ...
Kaiser
Yo no encontré mejor hasta ahora .. Esto es más una solución para algo que debería estar en el núcleo WP en mi opinión
CSAG
Si estuviera en el núcleo, otros escenarios no funcionarían.
kaiser
Este es un error conocido y está siendo rastreado en core.trac.wordpress.org/ticket/27282
Will.
La solución de @kaiser Ahmad M no tiene en cuenta las publicaciones fijas que habrían aparecido en la primera página, independientemente de su estado fijo. Puede dar lugar a que aparezcan muy pocas publicaciones en la primera página (WordPress v4.9.7). Esta respuesta es mejor porque explica eso.
Jacob Budin
0

Limpié ambas respuestas anteriores en una para que no cargue WP_Query innecesario, arregle si es pegajoso en la primera página, reduzca el tiempo para procesar la información con un código más rápido y limpio.

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
fuente