Blog

WordPressで指定の投稿を優先表示させる

Posted by admin at 2:58 日時 2016/11/16

久々の WordPress ネタ。kurudriveさんがqiitaにアップしていた記事「WordPressで指定の投稿を優先表示させる」で

recommend_post の数字の大きさで並び替えてるけど、チェックの無い場合にわざわざ 0 を登録してくのが無駄なデータの蓄積で美しくないと思うのですが、そもそも 値の入ってるやつだけ先に表示とかする方法あるんですかね?

と投稿されていましたが、方法、あります!

通常のWP_Queryのパラメーターではカバーされていない条件なのでSQL文をフィルターで変えてしまいます。

<?php
// WP_Query の JOIN 句へのフィルター
add_filter( 'posts_join', function( $join, $query ) {
    global $wpdb;

    // 管理画面またはメインクエリ以外のときスキップ
    if (is_admin() || !$query->is_main_query()) {
        return $join;
    }

    // アーカイブまたはホームのとき
    if ($query->is_archive() || $query->is_home()) {
        // recommend_post というキーの wp_postmeta テーブルの中身を結合します
        $join .= " LEFT JOIN (select post_id, meta_key, meta_value from $wpdb->postmeta) AS recommend_post";
        $join .= " ON ($wpdb->posts.ID = recommend_post.post_id AND recommend_post.meta_key = 'recommend_post')";
    }

    return $join;
}, 10, 2);

// WP_Query の ORDER BY 句へのフィルター
add_filter( 'posts_orderby', function( $orderby, $query ) {
    // 管理画面またはメインクエリ以外のときスキップ
    if (is_admin() || ! $query->is_main_query()) {
        return $orderby;
    }

    // アーカイブまたはホームのとき
    if ($query->is_archive() || $query->is_home()) {
        // 何らかの値が入っているものを先頭に
        // ISNULL() 関数を使ってるのがポイント
        $orderby = 'ISNULL(recommend_post.meta_value) ASC, ' . $orderby;
    }

    return $orderby;
}, 10, 2);

余談ですがカスタムフィールドの値のソートは、そのままだと文字列扱いになるので、日付でソートしたいとか数値として扱いたいという場合は、meta_query内で個別にtypeを指定する必要がある。これに isnull とか増えてくれるとSQL書かなくていいんだけど、現在使えるのは 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED' の9種類。

<?php
$args = array(
    'meta_query' => array(
        'meta_price' => array(
            'key'     => 'price',
            'type'    => 'numeric'
        ),
        'meta_release' => array(
            'key'     => 'release',
            'type'    => 'date'
        )
    ),
    'orderby' => array(
        'meta_price'   => 'asc',
        'meta_release' => 'desc',
        'date'         => 'desc'
    )
);
$query = new WP_Query( $args );

Share this entry