東京都府中市、九段下のWEB制作会社Maromaroのブログです

2019.11.18

Sasaki

WordPressでピン留めした記事(レコメンド)を優先表示する方法

今回はWordpressでピン留めした(レコメンド)記事を優先的に表示する方法です。

functions.phpに下記を記述しましょう。

この例では、カスタムフィールド名「recommend_post」を利用した場合を想定しています。
また、カスタムフィールドの作成には「Advanced Custom Fields」を利用しています。

/*
 * ピン留めした記事を優先表示する
 * */
$recommend_post_flg = false;
add_filter('posts_join', function ($join, $query) {
  global $wpdb;
  global $recommend_post_flg;

  if (is_admin() ) {
    return $join;
  }
  if (
    (is_archive() && is_tax('article_cats') && $query->is_main_query()) ||
    $recommend_post_flg == true
  ) {
    // 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' AND recommend_post.meta_value = '1')";
  }

  return $join;
}, 10, 2);

// WP_Query の ORDER BY 句へのフィルター
add_filter('posts_orderby', function ($orderby, $query) {
  global $recommend_post_flg;
  // 管理画面のときスキップ
  if (is_admin() ) {
    return $orderby;
  }
  // アーカイブまたはホームのとき
  if (
  ( is_archive() && is_tax('article_cats') && $query->is_main_query() ) ||
    $recommend_post_flg == true) {
    // 何らかの値が入っているものを先頭に
    // ISNULL() 関数を使ってるのがポイント
    $orderby = 'ISNULL(recommend_post.meta_value) ASC, ' . $orderby;
  }

  return $orderby;
}, 10, 2);

下記のようにして、テンプレートに書き込めば表示できます。

$args = array(
'posts_per_page' => 2,
'post_type' => 'articles'
);
$recommend_post_flg = true;
$the_query = new WP_Query($args);
$recommend_post_flg = false;

もう少し詳しく知りたい人向けのコードを解説

// 下記はレコメンドの投稿なのかを判別するためのフラグです
$recommend_post_flg = false;

// posts_joinはWP検索時にフックされるフィルターで
// SQLのJOIN(結合)を利用する際に用います。
// 今回では、レコメンドされたカスタムフィールド一覧を結合しています。
add_filter('posts_join', function ($join, $query) {
  global $wpdb;
  global $recommend_post_flg;

  // 管理画面のときは不要なのでスキップしています。
  if (is_admin() ) {
    return $join;
  }
  // アーカイブまたは「メイン」クエリーのとき、またはrecommend_post_flgがある場合に限定しています。
  // 例えば、特定のカスタムタクソノミーなどに限定したい場合には、 && is_tax('カスタムタクソノミー名')などを追加すると更に適用範囲を限定できます。
  if (
    (is_archive() && $query->is_main_query()) ||
    $recommend_post_flg == true
  ) {
    // 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' AND recommend_post.meta_value = '1')";
  }

  return $join;
}, 10, 2);
// WP_Query の ORDER BY 句へのフィルターです。
// レコメンドを優先表示するために、ソート指定しています。
add_filter('posts_orderby', function ($orderby, $query) {
  global $recommend_post_flg;
  // 管理画面のときはスキップ
  if (is_admin() ) {
    return $orderby;
  }
  // アーカイブまたは「メイン」クエリーのとき、またはrecommend_post_flgがある場合に限定しています。
  // 例えば、特定のカスタムタクソノミーなどに限定したい場合には、 && is_tax('カスタムタクソノミー名')などを追加すると更に適用範囲を限定できます。
  if (
  ( is_archive() && $query->is_main_query() ) ||
    $recommend_post_flg == true) {
    // recommend_postに何らかの値が入っているものを先頭に
    // ISNULL() 関数を使ってるのがポイント
    $orderby = 'ISNULL(recommend_post.meta_value) ASC, ' . $orderby;
  }

  return $orderby;
}, 10, 2);

以上です。

以前クライアントワークで利用したコードのため、動かないなどありましたらご容赦ください。
\(^o^)/