it-swarm.com.de

"Sticky" Posts für jede Kategorie (archive.php)

Ich muss in der Lage sein, für jede Kategorie Haftnotizen zu erstellen. Der einfachste Weg, dies zu tun, schien darin zu bestehen, nur zwei Schleifen auf der Seite zu erstellen. Das habe ich geschrieben:

<?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; 

Leider funktioniert es nicht wie erwartet:

  1. Dadurch werden geklebte Objekte in ALLEN Kategorien ganz oben platziert, unabhängig davon, ob sie zu dieser Kategorie gehören oder nicht.
  2. Am seltsamsten: Wenn keine geklebten Beiträge vorhanden sind, werden alle Beiträge durch die "klebrige" Schleife angezeigt - und anschließend durch die normale Schleife wiederholt. Seltsam!

Was habe ich falsch gemacht? Mir ist klar, dass geklebte Posts zweimal angezeigt werden (einmal oben und wieder in der normalen Position), aber anders als das, was verursacht diese Probleme? : - /

2

Um dies zu vervollständigen, habe ich in den Kommentaren zu der vorliegenden Frage Folgendes gesagt

Nur um es kurz zu erklären: WP_Query schlägt in einigen Fällen, in denen leere Arrays an einige seiner Parameter übergeben werden, katastrophal fehl, anstatt wie erwartet auch ein leeres Array zurückzugeben, gibt WP_Query alle Posts zurück. Wie ich bereits sagte, müssen Sie die aktuelle Kategorie-ID abrufen und diese zum Filtern der Haftnotizen verwenden, um die richtigen Haftnotizen zu erhalten. Denken Sie daran, dass Sie bei Ihrer Vorgehensweise klebrige Posts aus der Hauptabfrage entfernen müssen, da Sie sonst Duplikate erhalten

Als alternative Lösung, die Hooks und Filter für die Hauptabfrage verwendet und von einer ähnlichen Frage/Antwort ausgeht, habe ich mir Folgendes ausgedacht: ( Code ist gut kommentiert, damit er verfolgt werden kann. CAVEAT : Dies ist jedoch ungetestet und benötigt mindestens 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 );
                }
            }
        }
    }
});

EINIGE ANMERKUNGEN:

  • Dies funktioniert nur mit der Standardtaxonomie category. Der Code kann leicht geändert werden (bitte ändern Sie dies entsprechend Ihren Anforderungen), um eine Taxonomie und deren relevante Begriffe zu verwenden

  • Sie fügen dies einfach zu functions.php hinzu. Sie müssen Ihre Vorlagendateien nicht ändern oder benutzerdefinierte Abfragen verwenden. Sie benötigen lediglich die Hauptabfrage mit der Standardschleife

BEARBEITEN

Der obige Code ist jetzt getestet und funktioniert unter Wordpress 4.2.1 und PHP 5.4+

3
Pieter Goosen

Ich kann die Antwort von Pieter Goosen aufgrund der Reputationsregeln nicht kommentieren/-:

Der aktuelle Code hat einen Nebeneffekt auf das aktuelle WordPress 4.8 (März 2018). Er zeigt beim Zugriff auf eine nicht vorhandene Seite störende Posts an, die stattdessen einen 404-Fehler auslösen sollten. Wie "www.example.com/asd", wo "asd" nicht existiert. Gleiches Problem gibt es "wp-admin". Dies liegt daran, dass in diesem Fall "asd" oder "wp-admin" in $ q als Kategoriename gespeichert wird, obwohl dies keine vorhandene Kategorie ist.

Korrektur: Überprüfen Sie, ob die übergebene Kategorie tatsächlich existiert, indem Sie die letzte Zeile dieses Codes in den oben angegebenen Code einfügen:

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   
3
bz-mof

Die Antwort auf beide Fragen war ziemlich einfach.

  1. Fügen Sie einfach ein Argument zu WP_Query hinzu, um die aktuelle Kategorie einzuschränken
  2. Stellen Sie sicher, dass WP_Query nicht ausgeführt wird, es sei denn, es gibt tatsächlich einige klebrige Beiträge

Wie so:

<?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; ?>
2