publicaciones “pegajosas” para cada categoría (archive.php)

2

Necesito tener la capacidad de tener publicaciones adhesivas para cada categoría. La forma más sencilla de hacer esto parecía ser simplemente crear dos bucles en la página. Esto es lo que escribí:

<?php
//Custom "sticky" loop
$sticky_posts = new WP_Query(array(
    'post__in' => get_option('sticky_posts')
));

if ($sticky_posts->have_posts()) :
    while ($sticky_posts->have_posts()) : $sticky_posts->the_post();

        get_template_part('post-formats/content', 'sticky');

    endwhile; endif;

// CLEAR DATA
wp_reset_postdata();

if (have_posts()) : 
// Normal loop

while (have_posts()) : the_post(); 

    $format = get_post_format();
    if (false === $format) {
        $format = 'standard';
    }
    get_template_part('post-formats/content', $format);

endwhile; 

Lamentablemente no funciona como se esperaba:

  1. Esto coloca los elementos pegados en la parte superior de TODAS las categorías, pertenezcan o no a esa categoría.
  2. Lo más extraño de todo es que: si no hay publicaciones pegadas en, todas las publicaciones se muestran con el bucle "pegajoso" y luego se repiten a continuación con el bucle normal. ¡Raro!

¿Qué he hecho mal? Me doy cuenta de que las publicaciones adhesivas aparecerán dos veces (una vez en la parte superior y otra vez en su posición normal), pero aparte de eso, ¿qué está causando estos problemas? : - /

    
pregunta Django Reinhardt 04.06.2015 - 13:00

3 respuestas

3

Para hacer esto más completo, esto es lo que he dicho en los comentarios en respuesta a la pregunta en cuestión

  

Solo para explicar rápidamente, WP_Query falla catastróficamente en algunos casos donde las matrices vacías se pasan a algunos de sus parámetros, en lugar de devolver una matriz vacía como es de esperar, WP_Query devuelve todas las publicaciones. En cuanto a obtener las notas correctas, como dije antes, necesita obtener la identificación de la categoría actual y usarla para filtrar las publicaciones adhesivas. Recuerde, con su enfoque, necesita eliminar las publicaciones adhesivas de la consulta principal, de lo contrario obtendrá duplicados

Como una solución alternativa utilizando ganchos y filtros en la consulta principal, y trabajando desde una pregunta / respuesta similar , esto es lo que he encontrado: ( El código está bien comentado, por lo que se puede seguir. PRECAUCIÓN: Sin embargo, esto no se ha probado y necesita al menos PHP 5.4+ )

function get_term_sticky_posts()
{
    // First check if we are on a category page, if not, return false
    if ( !is_category() )
        return false;

    // Secondly, check if we have stickies, return false on failure
    $stickies = get_option( 'sticky_posts' );

    if ( !$stickies )
        return false;

    // OK, we have stickies and we are on a category page, continue to execute. Get current object (category) ID
    $current_object = get_queried_object_id();

    // Create the query to get category specific stickies, just get post ID's though
    $args = [
        'nopaging' => true,
        'post__in' => $stickies,
        'cat' => $current_object,
        'ignore_sticky_posts' => 1,
        'fields' => 'ids'
    ];
    $q = get_posts( $args );

    return $q;
}

add_action( 'pre_get_posts', function ( $q )
{
    if (    !is_admin() // IMPORTANT, make sure to target front end only
         && $q->is_main_query() // IMPORTANT, make sure we only target the main query
         && $q->is_category() // Only target category archives
    ) {
        // Check if our function to get term related stickies exists to avoid fatal errors
        if ( function_exists( 'get_term_sticky_posts' ) ) {
            // check if we have stickies
            $stickies = get_term_sticky_posts();

            if ( $stickies ) {
                // Remove stickies from the main query to avoid duplicates
                $q->set( 'post__not_in', $stickies );

                // Check that we add stickies on the first page only, remove this check if you need stickies on all paged pages
                if ( !$q->is_paged() ) {

                    // Add stickies via the the_posts filter
                    add_filter( 'the_posts', function ( $posts ) use ( $stickies )
                    {   
                        $term_stickies = get_posts( ['post__in' => $stickies, 'nopaging' => true] );

                        $posts = array_merge( $term_stickies, $posts );

                        return $posts;
                    }, 10, 1 );
                }
            }
        }
    }
});

ALGUNAS NOTAS:

  • Esto solo funciona con la taxonomía predeterminada category . El código se puede modificar fácilmente (por favor haga eso, modifíquelo según sus necesidades) para usar cualquier taxonomía y sus términos relevantes

  • Simplemente agregas esto a functions.php. No es necesario alterar sus archivos de plantilla o el uso de consultas personalizadas. Todo lo que necesita es la consulta principal con el bucle predeterminado

EDITAR

El código anterior ahora está probado y funciona en Wordpress 4.2.1 y PHP 5.4+

    
respondido por el Pieter Goosen 04.06.2015 - 14:38
2

No puedo comentar la respuesta de Pieter Goosen debido a las reglas de reputación / -:

El código actual tiene un efecto colateral en wordpress 4.8 (marzo de 2018), muestra publicaciones pegajosas al acceder a una página que no existe, lo que debería dar un error 404 en su lugar. Como "www.example.com/asd" donde "asd" no existe. El mismo problema es "wp-admin". Esto se debe a que en ese caso "asd" o "wp-admin" se guardan en $ q como nombre de categoría, aunque no es una categoría existente.

Solución: compruebe si la categoría aprobada realmente existe agregando la última línea de este código en el código publicado anteriormente:

if (    !is_admin() // IMPORTANT, make sure to target front end only
     && $q->is_main_query() // IMPORTANT, make sure we only target the main query
     && $q->is_category() // Only target category archives         
     && $q->is_tax(get_query_var ( 'category_name')) // Only target existing category names   
    
respondido por el bz-mof 05.04.2018 - 22:24
1

La respuesta a ambos problemas fue bastante simple.

  1. Simplemente agregue un argumento a WP_Query para limitarlo a la categoría actual
  2. Asegúrate de que WP_Query no se ejecute a menos que haya realmente algunas publicaciones pegajosas

Me gusta así:

<?php
// Get sticky posts
$sticky_ids = get_option( 'sticky_posts' );

// BEGIN Custom "sticky" loop

// If sticky posts found...
if(!empty($sticky_ids)) {
    $args = array(
        'post_type' => 'post',
        'category__in' => get_query_var('cat'), // Get current category only
        'post__in' => get_option('sticky_posts') // Get stickied posts
    );

    $sticky_posts = new WP_Query($args);

    if ($sticky_posts->have_posts()) :
        while ($sticky_posts->have_posts()) : $sticky_posts->the_post();

            get_template_part('post-formats/content', 'sticky');

    endwhile; endif;
// END Custom "sticky" loop

    // Reset post data ready for next loop
    wp_reset_postdata();
}

if (have_posts()) :

    /* Start the Loop */
    while (have_posts()) : the_post();

        $format = get_post_format();
        if (false === $format) {
            $format = 'standard';
        }
        get_template_part('post-formats/content', $format);

    endwhile; endif; ?>
    
respondido por el Django Reinhardt 04.06.2015 - 14:17

Lea otras preguntas en las etiquetas