Wie ordne ich Elemente aus WP_Query neu an?

Ich habe dieses Stück Code:

$normal_args = array( 'order' => 'desc', 'ignore_sticky_posts' => 1, 'meta_query' => array( array( 'key' => 'rw_show_at_position', 'value' => '1', 'compare' => '=' ) ), 'post__not_in' => $prev_post_ids, 'post_status' => 'publish', 'posts_per_page' => get_option( 'column_right' ), 'post_type' => array( 'opinion', 'especiales', 'clasificados', 'portadadeldia', 'anunciantes', 'post', 'pages', 'esp-publicitarios' ) ); $normal_query = new WP_Query( $normal_args ); $i = 0; if ( $normal_query->have_posts() ) { while ( $normal_query->have_posts() ) { $normal_query->the_post(); ?>  '; ?> ID ) == 'esp-publicitarios' ) { $adv_pos = rwmb_meta( 'rw_adversiting_position', 'type=select', $post->ID ); echo $adv_pos . EOL; } else { ?> // do something here <?php } $i ++; } } 

Und ich möchte Elemente basierend auf post_type und einem metakey rw_adversiting_position neu rw_adversiting_position und sie dann normal anzeigen. Gerade jetzt bekomme ich dieses Ergebnis:

 0 ==> 183034 ==> 9 1 ==> 183033 ==> 6 2 ==> 183032 ==> 3 3 ==> 183002 ==> 4 ==> 182973 ==> 5 ==> 182971 ==> 6 ==> 182969 ==> 7 ==> 182999 ==> 8 ==> 182997 ==> 9 ==> 182995 ==> 10 ==> 182962 ==> 11 ==> 182948 ==> 

Das liegt daran, dass nur die 0, 1 und 2 esp-publicitarios Post-Typen sind. Die Nummer auf der rechten Seite 9, 6 und 3 ist die Position, an die ich den Gegenstand schieben soll.

 0 ==> 183002 ==> 1 ==> 182973 ==> 2 ==> 182971 ==> 2 ==> 183032 ==> 3 4 ==> 182969 ==> 5 ==> 182999 ==> 6 ==> 183033 ==> 6 7 ==> 182997 ==> 8 ==> 182995 ==> 9 ==> 183034 ==> 9 10 ==> 182962 ==> 11 ==> 182948 ==> 

Kann mir irgendwer ein paar Ideen geben, um das zu erreichen?

AKTUALISIEREN 1

Ich habe das gefunden, aber ich weiß nicht, wie ich es anwenden soll.

UPDATE 2

Dies ist der PHP-Code für die Sortierung, sort_position könnte rw_adversiting_position :

 $arr = [ '183034' => [ 'sort_position' => 9 ], '183033' => [ 'sort_position' => 5 ], '183032' => [ 'sort_position' => 3 ], '183002' => [ ], '182973' => [ ], '182971' => [ ], '182969' => [ ], '182999' => [ ], '182997' => [ ], '182995' => [ ], '182962' => [ ], '182948' => [ ] ]; $count = count( $arr ); $has_sortorder = [ ]; $no_sortorder = [ ]; krsort( $arr ); foreach ( $arr as $key => $val ) { if ( isset( $val['sort_position'] ) ) { $has_sortorder[ $val['sort_position'] ] = [ $key, $val ]; } else { $no_sortorder[] = [ $key, $val ]; } } $out = [ ]; for ( $i = 0; $i < $count; $i ++ ) { if ( isset( $has_sortorder[ $i ] ) ) { $out[ $has_sortorder[ $i ][0] ] = $has_sortorder[ $i ][1]; } else { $element = array_shift( $no_sortorder ); $out[ $element[0] ] = $element[1]; } } var_dump( $out ); 

Ich muss nur wissen, wie man das auf WP_Query anwendet, bevor man das Ergebnis bekommt, irgendwas?

AKTUALISIEREN 3

Hier ist ein Ausschnitt aus var_export($normal_query->posts) wie Sie sehen können, gibt es keinen Meta-Key, also kann ich basierend auf Werten eines var_export($normal_query->posts) bestellen, wie?

 $var = array( 0 => WP_Post::__set_state( array( 'ID' => 183034, 'post_author' => '4', 'post_date' => '2015-12-01 16:44:35', 'post_date_gmt' => '2015-12-01 21:14:35', 'post_content' => '', 'post_title' => 'Espacio Pub 3', 'post_excerpt' => '', 'post_status' => 'publish', 'comment_status' => 'closed', 'ping_status' => 'closed', 'post_password' => '', 'post_name' => 'espacio-pub-3', 'to_ping' => '', 'pinged' => '', 'post_modified' => '2015-12-01 16:54:38', 'post_modified_gmt' => '2015-12-01 21:24:38', 'post_content_filtered' => '', 'post_parent' => 0, 'guid' => 'http://elclarinweb.local/?post_type=esp-publicitarios&p=183034', 'menu_order' => 0, 'post_type' => 'esp-publicitarios', 'post_mime_type' => '', 'comment_count' => '0', 'filter' => 'raw', ) ), 1 => WP_Post::__set_state( array( 'ID' => 183033, 'post_author' => '4', 'post_date' => '2015-12-01 16:44:13', 'post_date_gmt' => '2015-12-01 21:14:13', 'post_content' => '', 'post_title' => 'Espacio Pub 2', 'post_excerpt' => '', 'post_status' => 'publish', 'comment_status' => 'closed', 'ping_status' => 'closed', 'post_password' => '', 'post_name' => '183033', 'to_ping' => '', 'pinged' => '', 'post_modified' => '2015-12-01 16:44:21', 'post_modified_gmt' => '2015-12-01 21:14:21', 'post_content_filtered' => '', 'post_parent' => 0, 'guid' => 'http://elclarinweb.local/?post_type=esp-publicitarios&p=183033', 'menu_order' => 0, 'post_type' => 'esp-publicitarios', 'post_mime_type' => '', 'comment_count' => '0', 'filter' => 'raw', ) ), 2 => WP_Post::__set_state( array( 'ID' => 183032, 'post_author' => '4', 'post_date' => '2015-12-01 15:53:56', 'post_date_gmt' => '2015-12-01 20:23:56', 'post_content' => '', 'post_title' => 'Publicidad 1', 'post_excerpt' => '', 'post_status' => 'publish', 'comment_status' => 'closed', 'ping_status' => 'closed', 'post_password' => '', 'post_name' => 'publicidad-1', 'to_ping' => '', 'pinged' => '', 'post_modified' => '2015-12-01 15:53:56', 'post_modified_gmt' => '2015-12-01 20:23:56', 'post_content_filtered' => '', 'post_parent' => 0, 'guid' => 'http://elclarinweb.local/?post_type=esp-publicitarios&p=183032', 'menu_order' => 0, 'post_type' => 'esp-publicitarios', 'post_mime_type' => '', 'comment_count' => '0', 'filter' => 'raw', ) ), 3 => WP_Post::__set_state( array( 'ID' => 183002, 'post_author' => '7', 'post_date' => '2015-11-22 00:08:00', 'post_date_gmt' => '2015-11-22 04:38:00', 'post_content' => 'Borrón y cuenta nueva es lo que han hecho los Bravos de Margarita en este comienzo de la segunda parte de la campaña, en la que ayer sumaron su cuarto triunfo seguido, al vencer a los Tiburones de La Guaira 5 carreras por 3. Margarita, que ganó dos de tres ante los escualos en la semana, madrugó al dominicano Alexis Candelario, quien llegó a dicha cita como el mejor lanzador del campeonato. Los artilleros isleños fabricaron cuatro de sus cinco carreras en las primeras dos entradas, catapultados por un doble impulsor de dos de Eliézer Alfonzo. “No importa quién esté en la lomita contraria, siempre que los muchachos crean en ellos mismos, estos van a ser los resultados”, señaló el dirigente Henry Blanco. Bravos se haría presente en el marcador una vez más en el sexto con doble remolcador del jardinero Junior Sosa y aguantaría un intento de remontada de los litoralenses en la parte final para sellar el lauro. “La mentalidad que tenemos es no pensar en la primera parte, hay que salir a ganar”, indicó Alfonzo, quien cerró el cotejo de 5-2 con un par de impulsadas y ahora acumula cinco rayitas traídas al plato en los últimos dos desafíos. “Estaba bastante perdido cuando comenzó la temporada, pero he hecho el ajuste necesario”.', 'post_title' => 'Ahora Bravos es puntero de la LVBP', 'post_excerpt' => 'Las curiosidades del nuevo sistema de puntos del torneo coloca al antiguo colero de puntero', 'post_status' => 'publish', 'comment_status' => 'open', 'ping_status' => 'open', 'post_password' => '', 'post_name' => 'ahora-bravos-es-puntero-de-la-lvbp', 'to_ping' => '', 'pinged' => '', 'post_modified' => '2015-11-22 00:08:00', 'post_modified_gmt' => '2015-11-22 04:38:00', 'post_content_filtered' => '', 'post_parent' => 0, 'guid' => 'http://elclarinweb.local/?p=183002', 'menu_order' => 0, 'post_type' => 'post', 'post_mime_type' => '', 'comment_count' => '0', 'filter' => 'raw' ) ) ); 

UPDATE 4

@bosco Ich habe einige Minderungen an deinem Code vorgenommen und nun sieht es wie folgt aus:

 function wpse_210493_apply_advertising_position( &$posts, $return = false ) { $ad_posts = array(); // Seperate $posts into "Ads" and "Content" arrays based on whether or not they have 'rw_adversiting_position' meta-data foreach ( $posts as $post ) { $position = intval( get_post_meta( $post->ID, 'rw_adversiting_position', true ) ); $post_date = $post->post_date; $post_modified = $post->post_modified; if ( ! empty( $position ) ) { if ( ! empty ( $ad_posts ) ) { if ( $post_date > $ad_posts[ $position ]->post_date || $post_modified > $ad_posts[ $position ]->post_modified ) { $ad_posts[ $position ] = $post; } } else { $ad_posts[ $position ] = $post; } } else { $content_posts[] = $post; } } // Sort the ads from smallest position index to greatest such that re-insertion properly factors in all ads ksort( $ad_posts ); // Add the ads back into the content at their specified positions foreach ( $ad_posts as $position => $ad ) { array_splice( $content_posts, $position, 0, array( $ad ) ); } // If $return is true, return the resulting array. Otherwise replace the original $posts array with it. if ( $return ) { return $content_posts; } else { $posts = $content_posts; } } 

Wenn ich dies auf der Vorlage debugge, bekomme ich folgende Ausgabe:

 echo '
 BEFORE'; echo count($normal_query->posts); echo '

'; wpse_210493_apply_advertising_position( $normal_query->posts ); echo '

 AFTER'; echo count($normal_query->posts); echo '

'; // Output BEFORE25 AFTER23

Der AFTER ist der richtige Wert, aber die Schleife verwendet den BEFORE und fügt zu leeren Elementen in der Schleife hinzu, warum? Sehen Sie dieses Bild für mehr Info.

Solutions Collecting From Web of "Wie ordne ich Elemente aus WP_Query neu an?"

Sie können die Metadaten-API verwenden , um die Metadaten von rw_advertising_position für jeden Beitrag rw_advertising_position , die Anzeigen vom Inhalt zu rw_advertising_position und die Anzeigen dann wieder an den richtigen Stellen einzufügen:

 /** * Extracts from an array posts with positional metadata and re-inserts them at the proper * indices. See https://wordpress.stackexchange.com/questions/210493 **/ function wpse_210493_apply_advertising_position( &$posts, $return = false ) { $ad_posts = array(); $content_posts = array(); // Seperate $posts into "Ads" and "Content" arrays based on whether or not they have 'rw_adversiting_position' meta-data foreach( $posts as $post ) { $position = get_post_meta( $post->ID, 'rw_adversiting_position', true ); if( ! empty( $position ) ) $ad_posts[ intval( $position ) ] = $post; else $content_posts[] = $post; } // Sort the ads from smallest position index to greatest such that re-insertion properly factors in all ads ksort( $ad_posts ); // Add the ads back into the content at their specified positions foreach( $ad_posts as $position => $ad ) { array_splice( $content_posts, $position, 0, array( $ad ) ); } // If $return is true, return the resulting array. Otherwise replace the original $posts array with it. if( $return ) return $content_posts; else $posts = $content_posts; } 

HAFTUNGSAUSSCHLUSS

Im obigen Beispiel spezifiziere ich einen functionsparameter &$posts der PHP anweist, eine Pass-by-Reference- Auswertungsstrategie für das Argument zu verwenden, das als $posts an die function übergeben wird. Das bedeutet, dass die Variable $posts auf die Daten an ihrem ursprünglichen Platz im Speicher verweist, anstatt auf eine lokal begrenzte Kopie der Daten zu verweisen, die als erstes Argument übergeben wurden.

Hier habe ich diesen Mechanismus verwendet, um die (Standard) -Option zur Verfügung zu stellen, um ein Array von Post-Objekten direkt neu anzuordnen, ohne einen Rückgabewert verarbeiten zu müssen. Da die function selbst nur ein Array sortiert, überlasse ich das Array-Argument als Referenz, um ein konsistenteres Verhalten mit allen 12 Array-Sortierfunktionen von PHP zu erreichen .

Wie @Andrei Gheorghiu in den Kommentaren darauf hinweist, kann die Weitergabe per Referenz zu unerwarteten Ergebnissen führen, wenn Sie mit der Übung nicht vertraut sind. In einem solchen Szenario sollten Sie sich davon fernhalten, indem Sie das $return Argument im Beispiel auf ” true oder die Option vollständig entfernen, wie Andrei es getan hat .

In deiner Vorlage:

 // [...] $normal_query = new WP_Query( $normal_args ); wpse_210493_apply_advertising_position( $normal_query->posts ); if ( $normal_query->have_posts() ) { // [...] 

Ich habe diesen Code nicht getestet – er dient nur der Veranschaulichung.

Alternativ dazu funktioniert die Verwendung einer zweiten Abfrage zum Abrufen der Anzeigen möglicherweise etwas besser.

Dies ist eine überarbeitete Version der Antwort von bosco, die die Frage beantwortet, aber zu viel Flexibilität hinzufügt, indem sie eine direkte Änderung von Abfrageeigenschaften erlaubt, die ich persönlich für eine schlechte Praxis halte.

 function wpse_210493_apply_advertising_position( $posts ) { $ad_posts = array(); $content_posts = array(); // Seperate $posts into "Ads" and "Content" arrays based on whether or not they have 'rw_adversiting_position' meta-data foreach( $posts as $post ) { $position = get_post_meta( $post->ID, 'rw_adversiting_position', true ); if( ! empty( $position ) ) $ad_posts[ intval( $position ) ] = $post; else $content_posts[] = $post; } // Sort the ads from smallest position index to greatest such that re-insertion properly factors in all ads ksort( $ad_posts ); // Add the ads back into the content at their specified positions foreach( $ad_posts as $position => $ad ) { array_splice( $content_posts, $position, 0, array( $ad ) ); } return $content_posts; } 

Nach dem Ausführen des Filters überprüfen wir, ob Posts zurückgegeben wurden, und wenn dies der foreach , verwenden wir sie in einer foreach , die unser Ergebnis ausgibt:

 $normal_query = new WP_Query( $normal_args ); $filtered_posts = wpse_210493_apply_advertising_position( $normal_query->posts ); if ( count($filtered_posts) ) : foreach ($filtered_posts as $post) : setup_postdata($post); /* run any functions available in WP loop here * (the_title(), the_content(), etc...) * */ endforeach; wp_reset_postdata(); endif;