一覧ページの表示順をクリック一つで変更

一覧ページの表示順をクリック一つで変更
Image by Lothar Dieterich from Pixabay

2023.03.17(更新日:2023.03.17)

アーカイブページやタクソノミーページなどでのお話。
通常「ASC or DESC」でループすれば済むところを「○○順」なんてボタンパーツを希望されたりしませんか?
それも基準値をカスタムフィールド値とかにされると「面倒くせー!」となる。
そんなに需要があるのか?と疑いつつも希望されると仕方がない。
すぐ忘れるのそのでまとめ。

この記事は1年以上経過しています。内容的に古い場合があります。

通常ループ

WordPressはそれぞれのページに適した記事データを取得してくれるので「降順」であれば何もすることはない。
けれど今回、その順番をいじくるのでとりあず「WP_Query」の出番かなと。
単純に「降順 / 昇順」オンリーのものは以下になる。

/* テンプレート内 */
<?php
$args = array(
  'post_type' => $post_type, //投稿タイプ
  'orderby' => 'date', //何を表示順の基準とするか
  'order' => 'DESC', //昇順か降順
  'post_status' => 'publish', //公開状態
  'posts_per_page' => -1, //何件表示か(-1で全件)
  'tax_query' => array( //カテゴリーなどのタクソノミーのタームを指定したい場合
    array(
      'taxonomy' => $taxonomy, //タクソノミー
      'field' => 'slug', //タームの絞り込む種別
      'terms' => $terms //その値
    )
  )
);
$loop = new WP_Query( $args );
if( $loop->have_posts() ) : 
  while( $loop->have_posts() ) : $loop->the_post();
//何か処理する
  endwhile;
endif;
wp_reset_postdata(); //必須。WP_Queryを使ったら書く!
?>

なぜか良く「どっちだっけ?」となるので念のため。「order」部分に入る値は

  • ASC・・・昇順(小さいもの順/例:123)
  • DESC・・・降順(大きいもの順/例:321)

になる。ちなみにデフォルトでは「DESC」。WP_Queryは各値を変えたら、どーにでもなると言う素晴らしい代物。

配列の中身を変える

上記のコードで「昇順 / 降順」に変える方法はご理解いただけると思う。
ではカスタムフィールドではどうするかだが

/* 引数 */
$args = array(
  'post_type' => $post_type, //投稿タイプ
  'meta_key' => $meta_key, //カスタムフィールドのキー
  'orderby' => 'meta_value', //何を表示順の基準とするか
  'order' => 'DESC', //昇順か降順
  ⋮
);

で出来るはず。もちろん「meta_value」が比較出来る値(数値や日付など)が前提。

分岐をどうするか

ここまでで引数の値を変えて「WP_Query」にぶち込めば問題ないことがわかる。
どう分岐させるかはURLパラメータで処理する・・・なんだが何でもかんでも使える訳ではない。
予め登録されているもの以外は登録しないと使えないので

/* functions.phpとかに付加 */
function custom_query_vars( $vars ) {
   $vars[] = 'meta_key';
    ⋮ //上の行の要領で付加
   return $vars; 
} 
add_filter( 'query_vars', 'custom_query_vars' );

の様に登録設定する。デフォルトで使えるパラメータは以下参照。

表示順切り替え用のリンクを設置

表示切り替え用のリンクにはパラメータを付加したものを使う。
以下の例はカスタム投稿のアーカイブページの例。パラメータは仕様に合わせて変更。

/* テンプレート内 */
<?php
$archive_link = get_post_type_archive_link( $post_type );
$desc = esc_url( add_query_arg( 'order', 'desc', $archive_link ) );
$asc = esc_url( add_query_arg( 'order', 'asc', $archive_link ) );
//orderbyやら複数入れ替えるなら以下の感じで
$field = esc_url( add_query_arg( array('order'=>'desc', 'meta_key'=>$meta_key ), $archive_link ) );
?> 
<ul> 
  <li><a href="<?php echo $desc; ?>">降順</a></li> 
  <li><a href="<?php echo $asc; ?>">昇順</a></li> 
  <li><a href="<?php echo $field; ?>">カスタムフィールド順</a></li> 
</ul>

パラメータで分岐

ここまで出来たら、パラメータを受け取って分岐するだけ。

/* WP_Query処理の前に */
$order = get_query_var( 'order' );
$meta_key = get_query_var( 'meta_key' );
// ⋮ とパラメータを受け取って
$args = array( //基本的に変わらない部分のみ入れといて 'post_type' => $post_type, //投稿タイプ ⋮ ); if( !empty( $order ) ) $args[ 'order' ] = $order; if( !empty( $meta_key ) ) $args[ 'meta_key' ] = $meta_key; // ⋮ と$argsに追加
$loop = new WP_Query( $args );

ゴチャゴチャになる場合は、それぞれ配列の引数をちゃんと書いて分けた方がいいかも。間違いないし可視性もいいしね。