it-swarm.com.de

Benutzerdefinierte Abfrage - Alternative Beiträge nach Kategorie

Ich habe einen benutzerdefinierten Beitragstyp namens "Services" mit einer benutzerdefinierten Taxonomie namens "Location". Jeder Beitrag ist entweder als "Standort A" oder "Standort B" kategorisiert.

Ich muss alle Beiträge des Beitragstyps "Dienste" abfragen und nach Datum sortieren. Anstatt nur nach Datum aufzulisten, möchte ich die Beiträge nach Kategorien wie folgt abwechseln:

  1. Neuester Beitrag von "Location A"
  2. Neuester Beitrag von "Ort B"
  3. Zweitneuester Beitrag von "Location A"
  4. Zweitneuester Beitrag von "Location B"
  5. 3. neuster Beitrag von "Location A"
  6. 3. neuster Beitrag von "Location B"

usw...

Ist es möglich, die folgende Abfrage zu ändern, um dies zu erreichen? Oder muss ich einige fortgeschrittene Datenbank-Verknüpfungen usw. durchführen (wie Sie sich vorstellen können, sind mir diese Abfragen nicht vertraut).

<?php $args = array(
        'post_type' => 'services', 
        'posts_per_page' => '-1',
        'order_by' => 'date',
        'order' => 'DESC',
            'tax_query' => array(
                array(
                    'taxonomy' => 'location',
                    'field' => 'slug',
                    'terms' => array ('location-a', 'location-b')
                )
            )
        );
        $query = new WP_Query( $args );

        if (have_posts()) : while( $query->have_posts() ) : $query->the_post(); ?>

Zusätzliche Bemerkungen:

  • Es wird nicht eine gerade Anzahl von Posts in jeder Kategorie geben, daher muss die Abfrage fortgesetzt werden, um die Posts von Standort A aufzulisten, sobald Sie keine Posts von Standort B mehr haben, und umgekehrt.
  • Was passiert, wenn ein Beitrag in beide Kategorien eingeteilt wurde? Ich möchte nicht, dass es zweimal gezeigt wird.
  • Die benutzerdefinierte Taxonomie "Ort" wird von mehreren verschiedenen Beitragstypen verwendet. Ich möchte jedoch immer nur einen Beitragstyp abfragen.
  • Ich muss die Fähigkeit behalten, bestimmte Posts klebrig zu machen.

Ist das möglich? Vielen Dank.

3
LBF

BEARBEITEN

Nach Ihren Kommentaren habe ich die gesamte Lösung überarbeitet. Ich behalte die ursprüngliche Antwort nur als Referenz

Wenn ich 3 klebrige Beiträge habe, sollten sie nicht die ersten 3 Beiträge auf der ersten Seite sein, unabhängig von ihrem Beitragsdatum? Was passiert, ist, dass nur die klebrigen Beiträge, die sich zufällig in der ersten Gruppe von 10 Beiträgen befinden, basierend auf ihrem Datum, als klebrig behandelt werden. Der Rest der Haftnotizen wird oben auf der Seite angezeigt, auf die sie sich aufgrund ihres Datums beziehen. Wie kann ich sie unabhängig vom Datum oben auf der ERSTEN Seite anzeigen lassen?

Ich habe getestet, was Sie gesagt haben, und das Verhalten der Haftnotizen entspricht nicht meiner Erwartung, wenn eine Steuerabfrage mit einer neuen Instanz von WP_Query verwendet wird.

Mögliche Lösungen

  • Sie können einfach zwei Abfragen ausführen, eine für Haftnotizen und eine wie in meiner ursprünglichen Antwort beschrieben, und Haftnotizen einfach von der zweiten Abfrage ausschließen. Sie müssen nur die ursprüngliche Antwort ein wenig überarbeiten. Der Nachteil dabei ist, dass, wenn Sie genau 10 Posts pro Seite benötigen, dies nicht funktioniert. Damit es funktioniert, müssen Sie Offsets verwenden

  • Die Lösung, die ich gewählt habe, besteht darin, alle Zustände getrennt zu behandeln und später alle als einen zusammenzufassen

LÖSUNG

Ich habe hier einige Lösungen getestet, um die schnellste und ressourcenschonendste zu finden. Die Anforderungen, die im OP festgelegt sind, sind einzigartig. Daher ist diese Lösung höchstwahrscheinlich in anderen Situationen zu übertrieben, in denen Sie nicht nach Amtszeiten wechseln müssen, z. B. wenn Sie nur nach Datum geordnete und klebrige Stellen benötigen.

Die vollständige Lösung verwendet bis zu vier benutzerdefinierte Abfragen, und Sie könnten denken, dass dies ziemlich schwierig für die Datenbank ist, aber dies ist nicht der Fall. Im Gegenteil, dies ist tatsächlich zwei Mal schneller als meine ursprüngliche Antwort, da Sie nicht prüfen, ob ein Beitrag zu einem Begriff gehört oder nicht. Um dies erheblich zu beschleunigen, habe ich Transienten verwendet, wodurch diese Bearbeitung fast viermal schneller ist als meine ursprüngliche Antwort.

OK, lassen Sie uns Code: ( Ich gehe nicht auf Details zu bestimmten Punkten ein, wie es in der ursprünglichen Antwort behandelt wurde )

Ich habe mich entschlossen, zwei mögliche gebrauchte für die Haftnotizen zu posten, wie Sie sehen werden. Sie müssen entscheiden, wie Sie mit Stickies umgehen möchten, und dann den Kommentar- und Kommentarcode gemäß Ihren Anforderungen entfernen. Hier sind die beiden Methoden, die ich verwendet habe

  • Wenn Ihre Stickies alle innerhalb der beiden festgelegten Bedingungen liegen, können Sie den Code einfach so verwenden, wie er ist

  • Wenn Ihre Nachrichten Posts von außerhalb der beiden festgelegten Begriffe enthalten und Sie diejenigen ausschließen müssen, die nicht zu den beiden festgelegten Begriffen gehören, müssen Sie den nicht kommentierten Code auskommentieren und diese Zeile anschließend entfernen

    $q = array_merge( $sticky_post, $new_posts_array );
    

GRUNDLEGENDE INNERE FUNKTIONEN DES CODES

Die Posts (hier werden nur die Post-IDs abgerufen, um die Abfragen zu beschleunigen) aus einem bestimmten Begriff werden separat abgerufen. Der Grund dafür ist, dass alle Posts schneller abgerufen und anschließend nach Begriffen sortiert werden. Um sicherzustellen, dass Sie keine Duplikate erhalten, habe ich die zweite Abfrage so festgelegt, dass alle Posts ausgeschlossen werden, die zu beiden Begriffen gehören. Diese Posts werden nur von der ersten Abfrage abgerufen

Jedem der beiden zurückgegebenen Arrays werden dann neue Schlüssel zugewiesen. Ein Array hat gerade Schlüssel, das andere Array ungerade Schlüssel. Diese Arrays werden dann kombiniert und sortiert. Das neue Array enthält nun Posts von beiden Arrays, die abwechselnd nach Begriff sortiert sind

Der letzte Schritt ist das Hinzufügen der Haftnotizen. Was Sie jetzt haben, ist ein Array, das Beitrags-IDs, klebrige Beiträge zuerst, dann Beiträge enthält, die abwechselnd nach Begriff sortiert sind. Dieses Array von IDs wird in einem Übergang gespeichert, der alle 7 Tage aktualisiert wird (Sie können dies entsprechend einstellen) oder wenn ein Beitrag aktualisiert, gelöscht oder ein neuer Beitrag veröffentlicht wird.

Dieses Array von Beitrags-IDs wird jetzt wie gewohnt verwendet, um die Beiträge in einem new WP_Query anzuzeigen, und die Reihenfolge, nach der die Beitrags-IDs sortiert werden, wird verwendet, um die Beiträge zu sortieren. Hier ist der vollständige Code

if ( false === ( $q = get_transient( 'ordered_posts' ) ) ) {

    $sticky_post = get_option( 'sticky_posts' );
    /* 
     * Only do this if sticky posts can belong to terms outside the given two terms
     * and you only need to include sticky posts that belongs to the given two terms
     * Uncomment this part if needed
    */
    /* 
    if( $sticky_post ) {
        $sticky_args = array(
            'post_type'         => 'services', 
            'posts_per_page'    => -1,
            'post__in'          => $sticky_post,
            'fields'            => 'ids',
            'tax_query'         => array(
                array(
                    'taxonomy'  => 'location',
                    'field'     => 'slug',
                    'terms'     => array ('location-a', 'location-b' )
                )
            )
        );
        $sticky_query = get_posts( $sticky_args );
    }
    */

    $args1 = array(
        'post_type'         => 'services', 
        'posts_per_page'    => -1,
        'post__not_in'      => $sticky_post,
        'fields'            => 'ids',
        'tax_query'         => array(
            array(
                'taxonomy'  => 'location',
                'field'     => 'slug',
                'terms'     => array ('location-a')
            )
        )
    );
    $query1 = get_posts( $args1 );

    $new_posts_array1 = [];

    if( $query1 ) {
        $counter1 = 0;

        foreach ( $query1 as $post ) {
            $new_posts_array1[$counter1++ * 2] = $post;
        }
        unset( $post );
    }

    $args2 = array(
        'post_type'         => 'services', 
        'posts_per_page'    => -1,
        'post__not_in'      => $sticky_post,
        'fields'            => 'ids',
        'tax_query'         => array(
                array(
                    'taxonomy'  => 'location',
                    'field'     => 'slug',
                    'terms'     => array ('location-b')
                ),
                array(
                    'taxonomy'  => 'location',
                    'field'     => 'slug',
                    'terms'     => array ('location-a'),
                    'operator'  => 'NOT IN',
                )
            )
    );
    $query2 = get_posts( $args2 );

    $new_posts_array2 = [];

    if( $query2 ) {
        $counter2 = 0;

        foreach ( $query2 as $post ) {
            $new_posts_array2[($counter2++ * 2) + 1] = $post;
        }
        unset( $post );
    }


    $new_posts_array = $new_posts_array1 + $new_posts_array2;
    ksort( $new_posts_array );

    // Comment this line out if you uncommented the other block of code
    $q = array_merge( $sticky_post, $new_posts_array );

    /* 
     * If you going to use the first block of commented-out code
     * then you will need to uncomment this piece of code. Just remember
     * to comment the piece of code above out as stated. You cannot have both
     * pieces of code going at once
    */
    /*
    if( isset( $sticky_query ) ) {
        $q = array_merge( $sticky_query, $new_posts_array );
    }else{
        $q = $new_posts_array;
    }   
    */

    set_transient( 'ordered_posts', $q, 7 * DAY_IN_SECONDS );
}

$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args = array(
 'post_type' => 'services',
    'paged'                 => $paged,
    'posts_per_page'        => 5,
    'post__in'              => $q,
    'ignore_sticky_posts'   => 1,
    'orderby'               => 'post__in',
);
$query = new WP_Query( $args );

if ( $query->have_posts() ) {
    while ( $query->have_posts() ) {
        $query->the_post();

        get_template_part( 'content', get_post_format() );

    }

    next_posts_link( 'Older Entries', $query->max_num_pages ); //Remember the $max_pages parameter with custom queries
    previous_posts_link( 'Newer Entries' );

    wp_reset_postdata();
}

Fügen Sie dann in Ihrer functions.php den folgenden Code hinzu. Dies löscht den Übergang, wenn ein neuer Beitrag veröffentlicht oder ein Beitrag aktualisiert oder der Status eines Beitrags geändert wird

add_action( 'transition_post_status', function ( $new_status, $old_status, $post )
{
        delete_transient( 'ordered_posts' );

}, 10, 3 );

ENTFERNEN DES OBEN GENANNTEN CODES

Sobald ein Transient festgelegt ist, können Sie den Code darin nicht mehr ändern. Diese Änderungen werden nur angezeigt, wenn der Übergang abläuft oder wenn er gelöscht wird. Wenn der Code nicht funktioniert, gehen Sie wie folgt vor

  • Aktualisieren Sie zuerst einen Beitrag, um den Transienten zu löschen, oder löschen Sie ihn manuell aus der Datenbank

  • Dann entfernen Sie die beiden folgenden Zeilen

    if ( false === ( $q = get_transient( 'ordered_posts' ) ) ) {
    
  • und

    set_transient( 'ordered_posts', $q, 7 * DAY_IN_SECONDS );
        }
    
  • Dadurch wird der Transient aus der Einstellung entfernt.

  • Nachdem der Transient entfernt wurde, führen Sie eine var_dump( $var ) aller Variablen aus und prüfen Sie, ob Sie die gewünschte Ausgabe erhalten. Überprüfen Sie insbesondere die Abfragen und was zurückgegeben wird

    • Beispiel: Um das Ergebnis der Abfrage zu sichern, $query1

      var_dump( $query1 );
      

Dies sollte Ihnen eine Vorstellung davon geben, wo das Problem liegt. Wenn Sie die Ausgabe wie gewünscht erhalten, geben Sie die Zeilen zurück, die Sie für den Übergang gelöscht haben. Stellen Sie einfach doppelt sicher, dass der Transient gelöscht wurde, bevor Sie ihn zurücksetzen, sonst erhalten Sie die vorherigen Ergebnisse

URSPRÜNGLICHE ANTWORT

Diese Frage gab mir tatsächlich die Möglichkeit, mit Ideen herumzuspielen. Ich denke, diese Frage muss richtig beantwortet werden. Ich hoffe, dies beantwortet alle Ihre Fragen.

Sie können dies mit nur einer Abfrage tun. Das erste, was Sie tun müssen, ist, alle Ihre Beiträge aus den beiden Begriffen auf einmal abzurufen, wie Sie es bereits getan haben. Nur eine Anmerkung, Sie müssen keine Sortierreihenfolge festlegen, da date und DESC Standardeinstellungen sind.

Die benutzerdefinierte Taxonomie "Ort" wird von mehreren verschiedenen Beitragstypen verwendet. Ich möchte jedoch immer nur einen Beitragstyp abfragen.

Fügen Sie einfach den Parameter post_type zu Ihren Abfrageargumenten hinzu, um auf einen bestimmten Beitragstyp abzuzielen

<?php 
$args = array(
    'post_type' => 'services', 
    'posts_per_page' => '-1',
    'tax_query' => array(
            array(
                'taxonomy' => 'location',
                'field' => 'slug',
                'terms' => array ('location-a', 'location-b')
            )
        )
);
$query = new WP_Query( $args );

if( $query->have_posts() ) {

Sie müssen jetzt Ihr Array zurückgesendeter Posts in zwei separate Arrays aufteilen, ein Array für die Begriffe location-a und location-b und das für klebrige Posts. Das Array mit den zurückgegebenen Beiträgen befindet sich in $query->posts

Was passiert, wenn ein Beitrag in beide Kategorien eingeteilt wurde? Ich möchte nicht, dass es zweimal gezeigt wird.

Sie müssen sich vorher entscheiden, wie Sie entweder als location-a oder location-b behandeln möchten, andernfalls erhalten Sie möglicherweise eine Vervielfältigung. Nehmen wir an, wir behandeln sie als location-a

Ich muss die Fähigkeit behalten, bestimmte Posts klebrig zu machen.

Sticky-Posts werden oben in Ihrem zurückgegebenen Array angezeigt, und nach all dem Sortieren möchten wir sie unabhängig von der Laufzeit weiterhin oben behalten. Lassen Sie uns also alle klebrigen Posts von der Sortierung ausschließen und sie später so zurückgeben, wie sie sind

Sie können also so etwas tun

$counter1 = 0;
$counter2 = 0;

$new_posts_array = [];
$sticky = [];
foreach ( $query->posts as $post ) {
    if( is_sticky() ) {
       $sticky[] = $post;
    }elseif( has_term( 'location-a', 'location' ) && has_term( 'location-b', 'location' ) || has_term( 'location-a', 'location' ) ) {
       $new_posts_array[$counter1++ * 2] = $post;
    }else{
       $new_posts_array[($counter2++ * 2) + 1] = $post;
    }
}

Alle Probleme wurden jetzt behoben. Wir haben jetzt zwei Arrays, eines mit den Pfosten und eines mit den neu angeordneten Schlüsseln mit den Pfosten

Wir müssen jetzt das Array der Posts natürlich sortieren, damit die Schlüssel in der normalen Sortierreihenfolge ab 0 sind. ( Wir können auch alle Schlüssel "zurücksetzen", obwohl dies nicht notwendig ist )

ksort($new_posts_array);

Wir können jetzt unsere beiden Arrays zusammenführen, sodass wir wieder ein Array haben. In diesem Array werden unsere Beiträge angezeigt

$q = array_merge( $sticky, $new_posts_array );

Jetzt müssen Sie nur noch das ursprüngliche Post-Array entfernen, das ursprüngliche Post-Array mit unserem neu angeordneten Array zurücksetzen, die Schleife zurückspulen und sie erneut ausführen, um unsere Liste auszugeben

unset( $query->posts );
$query->posts = $q;

$query->rewind_posts();

while( $query->have_posts() ) { 
   $query->the_post();

  //Display loop elements

}
wp_reset_postdata();

}

JETZT ALLE ZUSAMMEN!!!

<?php 
$args = array(
    'post_type' => 'services', 
    'posts_per_page' => '-1',
    'tax_query' => array(
            array(
                'taxonomy' => 'location',
                'field' => 'slug',
                'terms' => array ('location-a', 'location-b')
            )
        )
);
$query = new WP_Query( $args );

if( $query->have_posts() ) {

    $counter1 = 0;
    $counter2 = 0;

    $new_posts_array = [];
    $sticky = [];
    foreach ( $query->posts as $post ) {
        if( is_sticky() ) {
           $sticky[] = $post;
        }elseif( has_term( 'location-a', 'location' ) && has_term( 'location-b', 'location' ) || has_term( 'location-a', 'location' ) ) {
           $new_posts_array[$counter1++ * 2] = $post;
        }else{
           $new_posts_array[($counter2++ * 2) + 1] = $post;
        }
    }

    ksort($new_posts_array);

    $q = array_merge( $sticky, $new_posts_array );

    unset( $query->posts );
    $query->posts = $q;

    $query->rewind_posts();

    while( $query->have_posts() ) { 
       $query->the_post();

      //Display loop elements like
      echo get_the_term_list( $post->ID, 'location');
      the_title(); 

    }
    wp_reset_postdata();

}

Abfrage mit Paginierung

// set the "paged" parameter (use 'page' if the query is on a static front page)
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args = array(
    'post_type'         => 'services', 
    'paged'             => $paged,
    'posts_per_page'    => '5',
    'tax_query'         => array(
            array(
                'taxonomy'  => 'location',
                'field'     => 'slug',
                'terms'     => array ('location-a', 'location-b')
            )
        )
);
$query = new WP_Query( $args );

if( $query->have_posts() ) {

    $counter1 = 0;
    $counter2 = 0;

    $new_posts_array = [];
    $sticky = [];
    foreach ( $query->posts as $post ) {
        if( is_sticky() ) {
           $sticky[] = $post;
        }elseif( has_term( 'location-a', 'location' ) && has_term( 'location-b', 'location' ) || has_term( 'location-a', 'location' ) ) {
           $new_posts_array[$counter1++ * 2] = $post;
        }else{
           $new_posts_array[($counter2++ * 2) + 1] = $post;
        }
    }

    ksort($new_posts_array);

    $q = array_merge( $sticky, $new_posts_array );

    unset( $query->posts );
    $query->posts = $q;

    $query->rewind_posts();

    while( $query->have_posts() ) { 
       $query->the_post();

      //Display loop elements like
      echo get_the_term_list( $post->ID, 'location');
      the_title(); 

    }

    next_posts_link( 'Older Entries', $query->max_num_pages ); //Remember the $max_pages parameter with custom queries
    previous_posts_link( 'Newer Entries' );


    wp_reset_postdata();

}
6
Pieter Goosen