※ もっと簡単に実装できる方法がありました! 追記 2015 12/25
前回WordPressの投稿の並び替え条件(orderby)を複数にする方法を書きました。
しかし、この方法ではorderbyを複数にすることはできましたが、それぞれの条件で並べ方(order)を指定することはできませんでした。
今回はorderbyを複数にして、それぞれの条件ごとにorderを指定できる方法をがんばります。
ORDER BY 節を変更するフィルター
posts_orderby
というフィルターを使えばWordPressが投稿を取ってくるのに発行するSQLクエリーのORDER BY節を変更することができるようです。
pre_get_posts
でorderby
とorder
を複数指定してどんなORDER BYができているのか調べてみます。
条件は前回の記事と同じで発売日(release_time
)というカスタムフィールドの値で並べて、発売日が同じだったら投稿日(date
)で並べます。今回はそれぞれの並べ方を変更したいので発売日(release_time
)は古い順(昇順)で、投稿日(date
)は新しい順(降順)にしたいと思います。
<?php // function.php function change_posts_query( $query ) { if( is_archive() ) { $query->set('meta_key', 'release_time'); $query->set('orderby', 'meta_value_num date'); // orderby のように スペース区切りで複数指定してみる $query->set('order', 'ASC DESC'); } } add_action('pre_get_posts', 'change_posts_query'); // ORDER BY節を変更するフィルター add_filter( 'posts_orderby','change_posts_orderby', 10, 2 ); function change_posts_orderby($orderby, $query) { // どんな ORDER BY になっているか見たいだけなのでとりあえず出力する var_dump($orderby); // 'wp_postmeta.meta_value+0 DESC, wp_posts.post_date DESC' // 変更しない場合も$orderby を返してあげないと上手く動作しなくなる return $orderby; }
どうやら、$query->set('order', $value)
はASC
かDESC
で指定しないとデフォルトのDESC
に置き換え得られてしまうようです。そしてorderby
も$query->setした値のままではないので引数の$orderby
を利用して新しいORDER BY節を作るようにすれば良さそうです。
並び方(order)を条件ごとに指定できるようにする
$query->set('order', $value)
では並び方(order)を複数渡すことができなかったので、新しくキーを作って並び方(order)を複数渡し、posts_orderby
フィルターでORDER BYを組み立てたいと思います。
<?php // function.php function change_posts_query( $query ) { if( is_archive() ) { $query->set('meta_key', 'release_time'); $query->set('orderby', 'meta_value_num date'); $query->set('order', 'DESC'); // 独自のキーを作って orderを指定する // orderby の指定の仕方と合わせて スペース区切りにすることにします $query->set('my_orders', 'ASC DESC'); } } add_action('pre_get_posts', 'change_posts_query'); // ORDER BY節を変更するフィルター add_filter( 'posts_orderby','change_posts_orderby', 10, 2 ); function change_posts_orderby($orderby, $query) { // my_orders をスペース区切りで配列に変換する。 ※ my_orders が無ければ値が0個の配列になる $orders = array_filter( explode(' ', strtoupper( $query->get('my_orders') )) ); // my_orders がある時だけORDER BY節を変更する if( count($orders) > 0 ) { $orderby_arg = array(); $order_arg = array('DESC', 'ASC'); // $orderby文のDESC, ASC を削除して , で分割 foreach( explode(',', str_replace($order_arg, '', $orderby)) as $i => $the_orderby ) { if( isset($orders[$i]) && in_array($orders[$i], $order_arg) ) { // 対応する order がある時 $orderby_arg[] = trim($the_orderby) . ' ' . $orders[$i]; } else { // 対応する order が無い あるいは DESC, ASCでない場合は デフォルト値 DESC を使う $orderby_arg[] = trim($the_orderby) . ' DESC'; } } // それぞれの orderby の入った配列を , で連結した文字列にする $orderby = implode(',', $orderby_arg); } return $orderby; }
これでorderby
、my_orders
ともにスペース区切りで対応した並べ方の条件(orderby)に対応する並べ方(order)を指定できるようになりました。
対応するorderが無かったりDESCやASCでない文字だった時はデフォルトのDESC
になるようになっているので、orderby
を3つ指定してmy_orders
は2つしか指定しなくても最後の条件は自動的にDESCが割当てられるようになっています。
[参考]
「ご注文はうさぎですか?」画集 Cafe du Lapin (まんがタイムKRコミックス)
- 作者: koi
- 出版社/メーカー: 芳文社
- 発売日: 2014/05/27
- メディア: コミック
- この商品を含むブログ (20件) を見る
追記 2015 12/25
※ もっと簡単に実装できる方法がありました!