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 );