私はこのコードを持っています:
$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(); ?>
<?php
echo $i . ' ==> ';
?>
<?php
if ( get_post_type( $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 ++;
}
}
そして、私はpost_type
とメタキーrw_adversiting_position
に基づいてアイテムを並べ替えて、それからそれらを普通に表示したいです。今私はこの結果を得ています:
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 ==>
これは、0、1、2のみがesp-publicitarios
投稿タイプであるためです。右側の9、6、および3の数字は、アイテムをプッシュする位置です。この情報があれば、結果は次のようになります。
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 ==>
これを実現するためのアイデアをいくつか教えてください。
UPDATE 1
私は これ を見つけましたが、それを適用する方法がわかりません。
UPDATE 2
これはソートを実行するためのPHPコードです。sort_position
は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 );
結果を取得する前に、これをWP_Queryに適用する方法を知っておく必要があるだけです。
UPDATE 3
メタキーがないのがわかるので、ここではvar_export($normal_query->posts)
の断片を示します。メタの値に基づいて注文することができます。
$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私はあなたのコードにいくつかのマイナーな変更を加えました、そして今それは以下のように見えます:
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;
}
}
テンプレートでこれをデバッグすると、次のような出力が得られます。
echo '<pre> BEFORE';
echo count($normal_query->posts);
echo '</pre>';
wpse_210493_apply_advertising_position( $normal_query->posts );
echo '<pre> AFTER';
echo count($normal_query->posts);
echo '</pre>';
// Output
BEFORE25
AFTER23
AFTERは正しい値ですが、ループはBEFOREを使用しており、ループの空の要素に追加されています。なぜですか?詳しくは この写真 をご覧ください。
Metadata API を使用して各投稿のrw_advertising_position
メタデータを取得し、コンテンツから広告を分離してから、適切な場所に広告を再挿入できます。
/**
* 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;
}
免責事項
上記の例では、関数に渡される引数に対して pass-by-reference 評価戦略を
&$posts
として使用するようにPHPに指示する関数パラメータ$posts
を指定します。これは、最初の引数として渡されたデータのローカルスコープのコピーを参照するのではなく、$posts
変数がメモリ内の元の場所でdata を参照することを意味します。ここでは、このメカニズムを使用して、戻り値を処理する必要なしにpostオブジェクトの配列を直接並べ替える(デフォルト)オプションを提供しました。関数自体は単に配列をソートするだけです。 PHPの12の配列ソート関数のすべて とより一貫した動作を提供するために、参照によって配列引数を渡すことにしました。
コメントの中で @Andrei Gheorghi が指摘しているように、慣習に慣れていない場合は参照渡しで予期しない結果が生じる可能性があります。このようなシナリオでは、例の
$return
引数をtrue
に設定するか、完全に安全な Andreiが持っているように完全にオプションを削除する を実行することでそれを回避できるかもしれません。
あなたのテンプレートで:
// [...]
$normal_query = new WP_Query( $normal_args );
wpse_210493_apply_advertising_position( $normal_query->posts );
if ( $normal_query->have_posts() ) {
// [...]
私はそのコードをテストしていません - それは単に説明目的のためです。
あるいは、広告だけを取得するために2番目のクエリを使用すると、もう少しうまくいく場合があります。
これは bosco's answerの修正版です。 質問に答えます しかし、クエリプロパティを直接変更することで柔軟性が高まります。個人的に悪い習慣を考えなさい。
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;
}
フィルタを実行した後、投稿が返されたかどうかを確認し、返された場合は結果を出力するforeach
でそれらを使用します。
$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;