質問を言い換える
私のカテゴリcar
のループ内で投稿を注文する必要があります。 car
のカテゴリページにアクセスする場合、最初に表示するにはBMW
とタグ付けされたすべての投稿が必要です。それからタグBMW
とタグ付けされていない他の投稿が必要です。
私のposts_per_page
が10の投稿を表示するように設定されていて、私が1ページ目にあり、10のうち3つの投稿がBMW
とタグ付けされている場合、これら3つの投稿は最初に現れなければなりません。をクリックして2ページ目に進むと、同じことが当てはまります。 BMW
とタグ付けされたこれら10の投稿のうち5つがある場合、それらも他の5つの投稿の前に最初に表示されなければなりません。
それは可能ですか?
loop_start
フックを使用して@PieterGoosenと@ialocinの両方の良い答えを単純化したものを次に示します。
add_action( 'loop_start', function( $q ) {
if( $q->is_main_query() && $q->is_category( 'car' ) )
usort( $q->posts, function( $a, $b ){
return -1 * has_tag( 'bmw', $a ) + 1 * has_tag( 'bmw', $b ); });
}, 10, 2 );
the_posts
フィルタにも同じ方法を使用できます。
更新:
ホームページの投稿を最初のカテゴリ名で並べ替えるには、たとえば次のようにします。
add_action( 'loop_start', function( $q ) {
if( $q->is_main_query() && $q->is_home() )
usort( $q->posts, function( $a, $b ){
return strcasecmp(
get_the_category( $a->ID )[0]->name,
get_the_category( $b->ID )[0]->name
);
});
}, 10, 2 );
大文字と小文字を区別しない文字列比較のために strcasecmp
を使用します。
ループ内でこの種のソートはできません。しかし、あなたはあなた自身の関数を書くことによってすることができます
これが私の解決策です: PS!ニーズPHP 5.4+
STEP 1
wpse161553_loop_sort($tag='')
という名前の関数を作成します。これはメインのクエリで単一のタグで動作します。
STEP 2
あなたはメインのクエリーからpostオブジェクトを取得する必要があります。それらはすでに利用可能で、$wp_query->posts;
によってアクセスすることができます。 (利用可能なオブジェクトの完全なリストとそれらへのアクセス方法については、 WP_Post
を参照してください。).
STEP 3
新しいカウンターを作成して開始します。このカウンタは後で配列キーを$wp_query->posts;
から変更するために使用されます。
STEP 4
バックエンドに設定されているposts_per_page
オプションを取得します。この値は、目的のタグを持たないすべての投稿のカウンタに追加されます。これにより、これらすべての投稿が目的のタグ投稿を超えて進みます。
STEP 5
ループ内で、 has_tag()
を使用して各投稿を目的のタグと照合します。投稿に目的のタグがある場合は、現在のカウンタ値をそのまま配列($c
)にプッシュします。投稿に目的のタグがない場合は、現在のカウンタの値にposts_per_page
の値を加えて$c
にプッシュします。
STEP 6
2つの配列を結合するには array_combine
を使用してください。新しく作成された配列$c
は、投稿の配列の配列キーを置き換えます
STEP 7
array_combine
で作成した新しい配列を新しいキーに従ってソートするには、 ksort
を使用します。これにより、投稿が投稿日順にソートされるように配列がソートされます。また、目的のタグの投稿が最初に表示され、次に残りの投稿が表示されます。
ステップ8
array-values
を使用してキーをリセットし、0
から開始して数値を1ずつ増やします。
STEP 9
ループを巻き戻すために、ループを巻き戻します。
STEP 10
$wp_query->posts
内の元の配列の設定を解除して、作成した新しい配列と置き換えます。 $wp_query->posts
は新しく順序付けされたポストオーダーを持つ配列を保持します
ALL TOGETHER NOW !!
次のコードはあなたのfunctions.phpに入ります
function wpse161553_loop_sort($tag='') {
global $wp_query;
$posts = $wp_query->posts; // Gets all post data from the main query
$c = []; // Going to hold an array of new keys for later use
if ( have_posts() ) {
$count = 0; //Start the counter
$ppp = get_option('posts_per_page'); // Gets the backend posts per page option set. Will be used in conjustion with the counter
while ( have_posts() ) {
the_post();
if( '' != $tag && has_tag($tag)) { // This will be the tag to test against, your desired tag
$c[] = $count++;
}else{
$c[] = $ppp + $count++; // Adds posts per page value to each count to advance posts without desired tag past desired tag
}
}
}
$posts_reordered = array_combine( $c, $posts ); // Reset each post from main query's key with the new keys created by $c
$posts_sorted = ksort($posts_reordered); // Sort the new array according to key
$posts_reordered = array_values($posts_reordered); // Reset keys to start at zero and increment by one
rewind_posts(); // Reset the loop so we can run the loop again
unset($wp_query->posts); //unset the original $wp_query->posts object array
$wp_query->posts = $posts_reordered; // Set $wp_query->posts to the new reordered array
}
ITの使い方
あなたのcategory.php、あるいはそれに関してはどんなテンプレートでも、ループのすぐ上に以下を貼り付けてください。他に何も変更する必要はありません。
wpse161553_loop_sort( 'NAME OF THE TAG TO APPEAR FIRST' );
NAME OF THE TAG TO APPEAR FIRST
は投稿が最初に現れる希望のタグの名前です。
アイデアのドラフトを簡単に概説しているだけなので、私はこれをまったく考えてテストしていないことに注意してください。あなたがこのようにソートアクションを実行できることは確かですが。さて、私が考えていたのは、なぜthe_posts
にフックしてソートをするためにusort
を使わないのかということです。それ以外のすべて、特に条件は、これがすべてのクエリで実行されるわけではなく、実際の使用例に依存することを確認するためのものです。
add_action(
'the_posts',
'wpse161553_posts_with_tags_on_top_of_category',
10,
2
);
function wpse161553_posts_with_tags_on_top_of_category(
$posts,
$wp_query
) {
// we want this for one specific category
$the_category = 'abc';
// we want the post with this tag on top
$the_tag = 'xyz';
if (
$wp_query->is_main_query()
&& is_category( $the_category )
) {
// getting an array of post ids from category with tag
$posts_with_tag = new WP_Query(
array(
'category_name' => $the_category,
'tag' => $the_tag,
'fields' => 'ids'
)
);
// performing usort on referenced posts object
usort(
$posts,
function (
$post
) use (
$posts_with_tag
) {
// puts posts from the $posts_with_tag->posts array to the top
if(
in_array (
$post->ID,
(array) $posts_with_tag->posts
)
) {
return -1;
} else {
return 1;
}
}
);
}
return $posts;
}