it-swarm.com.de

WP_Query: Warum ist Sticky Post nicht das erste Element in der Schleife?

Ich habe eine benutzerdefinierte WP_Query-Schleife, die auf meta_value-Variablen basiert:

$meta_cat = get_sub_field('category');
$posts = new WP_Query( array(
    'cat' => $meta_cat,
    'posts_per_page' => get_sub_field('recent_ppp'),
) );

Aber wenn ich einen Beitrag klebrig mache, wird er nicht als erstes Element in der while-Schleife angezeigt.

Ich weiß, dass ignore_sticky_posts standardmäßig auf false gesetzt ist, sodass ich mich nicht darum kümmern muss, ihn zu ändern. Ich habe auch versucht, in de order_by documentation nachzuschlagen, ob ein Wert mit einem klebrigen Beitrag zusammenhängt, aber nicht.

Obwohl der order_by => 'post__in' in der Nähe sein könnte:

Die Post-ID-Reihenfolge beibehalten, die im Array post__in angegeben ist

Aber wenn ich post__in => get_options('sticky_posts') setze only wird der Sticky Post angezeigt.

Ist dies überhaupt möglich, ohne zwei benutzerdefinierte Schleifen zu erstellen (eine für die klebrigen Pfosten und die andere für die anderen Pfosten)? Das wäre wirklich schlecht, da nicht alle Kategorien klebrige Pfosten enthalten.

5
ronnyrr

Wenn Sie sich den Quellcode angesehen haben, in dem Stickies enthalten sind, stellen wir die folgende Bedingung fest, bevor WP_Query weiterhin Sticky-Posts enthält

if (    $this->is_home 
     && $page <= 1 
     && is_array($sticky_posts) 
     && !empty($sticky_posts)  
     && !$q['ignore_sticky_posts'] 
) {

Der Big Game Player ist die is_home Bedingung. Bedingungen in WP_Query werden gemäß den übergebenen Argumenten festgelegt und nicht gemäß der Seite, auf der die Abfrage erfolgt. Da Sie cat als Argument übergeben, wird is_home auf false und is_category auf true gesetzt. Da is_home auf false gesetzt ist, schlägt die obige Bedingung fehl und Stickies sind nicht enthalten.

MÖGLICHE ARBEITSUMGEBUNG -  ungetestet

Wir können is_home manuell über pre_get_posts auf true setzen. Wir müssen lediglich 'wpse_is_home' => true, an Ihre benutzerdefinierte WP_Query-Instanz übergeben

Dann führen wir unsere pre_get_posts Aktion wie folgt aus

add_action( 'pre_get_posts', function ( $q )
{
    if ( true === $q->get( 'wpse_is_home' ) ) 
        $q->is_home = true;
});

BEARBEITEN

Wir möchten wahrscheinlich nur Stickies anzeigen, die für die abgefragte Kategorie relevant sind. In diesem Fall sollten wir Stickies entfernen, die nicht zu der bestimmten abgefragten Kategorie gehören

Wir können Folgendes versuchen, immer noch in unserer Aktion pre_get_posts

add_action( 'pre_get_posts', function ( $q )
{
    remove_action( current_action(), __FUNCTION__ );

    if ( true !== $q->get( 'wpse_is_home' ) )
        return;

    // Make sure get_sub_field exists, if not, bail
    if ( !function_exists( 'get_sub_field' ) )
        return;

    // Lets query everything to keep code clean
    $meta_cat = get_sub_field( 'category' ); // Copied from your code
    $meta_cat = filter_var( $meta_cat, FILTER_VALIDATE_INT );
    // Make sure we have a value, if not, bail
    if ( !$meta_cat )
        return;

    $q->set( 'cat', $meta_cat );

    // Set pagination if recent_ppp exists
    $ppp = get_sub_field( 'recent_ppp');
    $ppp = filter_var( $ppp, FILTER_VALIDATE_INT );
    if ( $ppp )
        $q->set( 'posts_per_page', $ppp );      

    // Set is_home to true 
    $q->is_home = true;

    // Get all stickies
    $stickies = get_option( 'sticky_posts' );
    // Make sure we have stickies, if not, bail
    if ( !$stickies )
        return;

    // Query the stickies according to category
    $args = [
        'post__in'            => $stickies,
        'posts_per_page'      => -1,
        'ignore_sticky_posts' => 1, // Ignore stickies
        'cat'                 => $meta_cat,
        'orderby'             => 'post__in',
        'order'               => 'ASC',
        'fields'              => 'ids' // Get only post ID's
    ];
    $valid_sticky_ids = get_posts( $args );

    // Make sure we have valid ids
    if ( !$valid_sticky_ids ) {
        $q->set( 'post__not_in', $stickies );
        return;
    }

    // Remove these ids from the sticky posts array
    $invalid_ids = array_diff( $stickies, $valid_sticky_ids );

    // Check if we still have ids left in $invalid_ids
    if ( !$invalid_ids )
        return;

    // Lets remove these invalid ids from our query
    $q->set( 'post__not_in', $invalid_ids );
});

Bevor wir unsere benutzerdefinierte Abfrage ausführen, müssen wir sicherstellen, dass get_sub_field vorhanden ist und vor allem, dass get_sub_field( 'category' ) festgelegt und gültig ist. Dies vermeidet einen katastrophalen Ausfall, der dazu führt, dass alle Posts zurückgeschickt werden.

Ihr WP_Query kann ungefähr so ​​aussehen, da wir nur 'wpse_is_home' => true übergeben müssen:

if (    function_exists( 'get_sub_field' )
     && filter_var( get_sub_field( 'category' ), FILTER_VALIDATE_INT )
) {
    $args = [
        'wpse_is_home' => true
    ];
    $posts_array = new WP_Query( $args ); // DO NOT USE $posts

    // Run your loop as normal
}

LAST EDIT

Code wird getestet und funktioniert wie erwartet

4
Pieter Goosen