Zufällige Sortierung innerhalb einer bereits sortierten Abfrage

Ich habe eine funktionierende Abfrage, die eine Reihe von benutzerdefinierten Posts zurückgibt, die nach ihrer Paket-ID (ASC) geordnet sind. Bei einer Abfrage mit 9 Ergebnissen kann dies beispielsweise wie folgt aussehen:

4 Posts (Post-IDs 1, 2, 3, 4) mit Paket-ID 1

3 Posts (Post-IDs 5,6,7) mit Paket-ID 2

2 Beiträge (Beitrags-IDs 8,9) mit Paket-ID 3

Wenn diese Beiträge angezeigt werden, sind sie immer in der gleichen Reihenfolge. Mit anderen Worten, sie werden in der Reihenfolge von Post-ID 1 bis Post-ID 9 angezeigt.

Was ich versuche zu erreichen, ist, die Ergebnisse jeder Teilmenge (definiert durch die Paket-ID) nach dem Zufallsprinzip zu sortieren. Auf diese Weise würden die Beiträge als solche angezeigt:

Zufällige Anzeige der Post IDs 1 bis 4 (zB 2,1,4,3)

Zufällige Anzeige der Post-IDs 5 bis 7 (zB 6,5,7)

Zufällige Anzeige der Post-IDs von 8 bis 9 (zB 8,9)

Die Beiträge werden also immer noch nach der Paket-ID gruppiert, aber die Beiträge in jedem Paket werden nach dem Zufallsprinzip angezeigt.

So sieht meine aktuelle Abfrage aus:

$args = array( 'post_type' => 'custom_post_type', 'post_status' => 'publish', 'posts_per_page' => 9, 'meta_key' => 'pkg_id', 'orderby' => 'pkg_id', 'order' => 'ASC' ); 

Was ich dachte, könnte ‘funktionieren’, aber nicht:

 $args = array( 'post_type' => 'custom_post_type', 'post_status' => 'publish', 'posts_per_page' => 9, 'meta_key' => 'pkg_id', 'orderby' => array( 'pkg_id' => 'ASC', 'rand' ) ); 

Irgendwelche Vorschläge wie ich völlig ratlos bin!

Solutions Collecting From Web of "Zufällige Sortierung innerhalb einer bereits sortierten Abfrage"

Es besteht keine Notwendigkeit, eine übermäßige Menge von Abfragen zu tun, um dies zu erreichen. Sie können immer noch nur eine Abfrage verwenden, den the_posts und etwas PHP, um Ihren Code nach Bedarf zu sortieren.

Ich nehme an, dass dies eine benutzerdefinierte Abfrage von dem ist, was ich in Ihrer Frage gelesen habe, damit wir Folgendes tun können:

  • Zuerst möchten wir einen benutzerdefinierten WP_Query Parameter WP_Query , so dass wir diesen Parameter als Auslöser für unseren the_posts Filter verwenden können. Wir werden diesen Parameter n wpse_custom_sort und es wird einen Wert von true annehmen, um den Filter auszulösen

  • Als Nächstes verwenden wir den Filter ” the_posts , um die Posts nach dem benutzerdefinierten Feld zu sortieren. Anschließend sortieren wir diese Posts nach dem benutzerdefinierten Feld und geben die sortierten Posts schließlich zurück

DER CODE

Nur ein paar Notizen

  • Der Code ist nicht getestet und benötigt mindestens PHP 5.4

  • Ich habe get_post_meta() , um die benutzerdefinierten Feldwerte pro Post zurückzugeben, da Sie ACF verwenden. Sie müssen dies möglicherweise anpassen, um get_field() . Ich bin nicht vertraut mit ACF, also müssen Sie diesen Teil sortieren. Die Logik würde jedoch immer noch dieselbe bleiben

  • Denken Sie daran, dass das Abfragen von benutzerdefinierten Feldern nicht zu zusätzlichen Abfragen führt, da diese zwischengespeichert werden. Dies ist also eine sehr schlanke, optimierte Methode, um Ihr Endziel zu erreichen

Hier ist der Code für die benutzerdefinierte Abfrage. Sie müssen lediglich den zusätzlichen Parameter zu Ihren Abfrageargumenten in Ihrer benutzerdefinierten Seitenvorlage hinzufügen

 // Run your query normally $args = [ 'wpse_custom_sort' => true, // This parameter will trigger or the_posts filter // Your query args here ]; $q = new WP_Query( $args ); // Your loop as normal 

Jetzt werden wir unseren Filter ausführen ( das geht in functions.php oder vorzugsweise in ein benutzerdefiniertes Plugin )

 /** * Function to flatten a multidimentional array (for later use) * * Credit to zdenko * @link https://gist.github.com/kohnmd/11197713 */ function flatten_array( $arg ) { return is_array( $arg ) ? array_reduce( $arg, function ( $c, $a ) { return array_merge( $c, flatten_array( $a ) ); }, [] ) : [$arg]; } // The the_posts filter add_filter( 'the_posts', function ( $posts, $q ) { // First we need remove our filter remove_filter( current_filter(), __FUNCTION__ ); // Check if our custom parameter is set and is true, if not, bail early if ( true !== $q->get( 'wpse_custom_sort' ) ) return $posts; // Before we do any work, and to avoid WSOD, make sure that the flatten_array function exists if ( !function_exists( 'flatten_array' ) ) return $posts; // Our custom parameter is available and true, lets continue // Loop through the posts $major_array = []; foreach ( $posts as $p ) { $meta = get_post_meta( $p->ID, 'pkg_id', true ); // Bail if we do not have a $meta value, just to be safe if ( !$meta ) continue; // Sanitize the value $meta = filter_var( $meta, FILTER_SANITIZE_STRING ); // Lets build our array $major_array[$meta][] = $p; } // Make sure we have a value for $major_array, if not, bail if ( !$major_array ) return $posts; // Lets randomize the posts under each custom field $sorted = []; foreach ( $major_array as $field ) $sorted[] = shuffle( $field ); // Lets flatten and return the array of posts $posts = flatten_array( $sorted ); return array_values( $posts ); }, 10, 2 ); 

Nicht möglich mit einer einzigen Abfrage, Sie müssten 3 separate Abfrage jedes auf die verschiedenen “Paket-IDs” und die Bestellung dieser Abfragen als Rand.

 $args1 = array( 'post_type' => 'custom_post_type', 'orderby' => 'rand', 'meta_query' => array( array( 'key' => 'pkg_id', 'value' => 1, // you will have to check if this is correct ) ) ); $args2 = array( 'post_type' => 'custom_post_type', 'orderby' => 'rand', 'meta_query' => array( array( 'key' => 'pkg_id', 'value' => 2, // you will have to check if this is correct ) ) ); $args3 = array( 'post_type' => 'custom_post_type', 'orderby' => 'rand', 'meta_query' => array( array( 'key' => 'pkg_id', 'value' => 3, // you will have to check if this is correct ) ) ); 

Dadurch werden Ihre Posts in ihre “Paket-IDs” getrennt und jeder Satz wird als “Zufall” bezeichnet

Wenn wir verwenden:

 $args = array( 'post_type' => 'custom_post_type', 'post_status' => 'publish', 'posts_per_page' => 9, 'meta_key' => 'pkg_id', 'orderby' => array( 'pkg_id' => 'ASC', 'rand' => 'DESC' ) ); 

dann bekommen wir den Bestellteil als:

 ORDER BY wp_postmeta.meta_value ASC, RAND() DESC 

Dies scheint zu funktionieren, aber die DESC wird nicht benötigt.

Beachten Sie jedoch, dass die Reihenfolge von RAND() nicht gut skaliert. Die Methode von @PieterGoosen könnte in diesem Fall besser für Sie geeignet sein.