【WordPress】カスタムフィールドの値で昇順に並べたときフィールドが空の投稿を一番最後にする方法

  • URLをコピーしました!

イベントの開催日など、投稿日付とは違うカスタムフィールドに入力された値の順で一覧ページを並び替えたいとします。

start_date というカスタムフィールドの値を使って昇順(ASC)に並び替える方法をとります。

しかし、start_date が空の投稿があるときには、単なる昇順では問題が出るためその解決方法までをまとめた記事です。

投稿日順に並んでいる一覧
目次

準備

カスタムフィールドの設定(Advanced Custome Fields デイトピッカー の場合)

表示フォーマットは好きな設定に、返り値のフォーマットは並び替えで利用したいので Ymd にしておきます。

表示テンプレートの設定(ループの中部分のみ)

ループの中のテンプレートはとりあえずこんな感じにします。

<div>
    <h2>
        <a href="<?php the_permalink(); ?>">
            <?php the_title(); ?>
        </a>
    </h2>
    <dl>
        <dt>開催日</dt>
        <dd>
            <?php
            if(get_field('start_date')){

                //開始日があれば、開始日の日付フォーマットを調整して表示
                $start_date = date_create(get_field('start_date'));
                echo date_format($start_date, 'Y年n月j日');
            }else{
                //開始日に入力がないなら未定に
                echo '未定';
            }
            ?>
        </dd>
    </dl>
</div>

カスタムフィールドの値を使って並び替える

投稿タイプ event の一覧を、カスタムフィールド start_date の昇順(日付が古い順)に並べます。

if ( have_posts() ) : while ( have_posts() ) : the_post(); で表示している一覧なら、functions.phpにpre_get_postsを使って以下のように。


add_action( 'pre_get_posts', function($query) {
    if ( is_admin() || ! $query->is_main_query() ){
        return;
    }
    if($query->is_post_type_archive('event')){
        $query->set('meta_key', 'start_date');
        $query->set('orderby', 'meta_value');
        $query->set('order', 'ASC');
    }
});

また、そうではなくnew WP_Query() を使って表示させている一覧なら、WP_Queryの引数をこんな感じに

    $args= array(
            'post_type'=>'event',
            'meta_key' =>'start_date',
            'orderby' =>'meta_value',
            'order' => 'ASC'
    );
    $event_query = new WP_Query($args);

昇順(ASC)にすると、フィールドが空のものが先頭に来てしまう。

並び替えはうまくできましたが、この場合、未定のもの(start_dateが空の投稿)は一番最後に来てほしいです…。

開催日順に並んでいる一覧。開催日未定のものが先頭にある。

カスタムフィールドを使ったorderbyを調整する

orderの設定にはASCかDESCしかなく、空は0(一番小さい値)として扱われるため、そのままでは目的が達成できません。

が、posts_orderby というフィルターを使って、orderbyの動きを変えることができます。

まずは以下のように、functions.phpに準備します。

add_filter( 'posts_orderby', function($orderby, $query ) {
    if ( $query->get( 'custom_orderby' ) ) {
        $orderby = 'wp_postmeta.meta_value+0 > 0 DESC, ' . $orderby;
    }
    return $orderby;
}, 10, 2);

そしてif ( have_posts() ) : while ( have_posts() ) : the_post(); で表示している一覧なら、pre_get_postsを以下のように。

add_action( 'pre_get_posts', function($query) {
    if ( is_admin() || ! $query->is_main_query() ){
        return;
    }
    if($query->is_post_type_archive('event')){
        $query->set('meta_key', 'start_date');
        $query->set('orderby', 'meta_value');
        $query->set('order', 'ASC');
        $query->set('custom_orderby', 'true'); // 追加
    }
});

そうではなくnew WP_Query() を使って表示させている一覧なら、WP_Queryの引数をこんな感じに。

    <?php
    $args= array(
            'post_type'=>'event',
            'meta_key' =>'start_date',
            'orderby' =>'meta_value',
            'order' => 'ASC',
            'custom_orderby' => true // 追加
    );
    $event_query = new WP_Query($args);

フィールドの値が空の投稿を一番下、それ以外は昇順で並べることができた。

これで無事に開催日フィールドが空の投稿を一番下に移動することができました。

開催日順に並んだ一覧。日程未定の記事は一番下に表示される。

参考:MySQLで数値の昇順の後に空値のレコードが並ぶようにする

参考:WP_Queryで本文欄に入力値があるものを優先表示したい | WordPress.org 日本語

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

コメントは日本語で入力してください。(スパム対策)

CAPTCHA

目次