質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.80%

【wordpress】検索キーワードが該当する投稿を優先して並べ替えたい

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 328

score 21

前提

wordpressを使って、クックパッドのようなサービスを作っています。
具体的には
・ユーザー登録
・ログイン、ログアウト
・レシピの投稿
・いいね、お気に入り機能
・検索機能
などを実装したクックパッドのクローンです。

webサービスの簡単な仕組み

プラグイン「user frontend」を使い、管理画面外から投稿が可能です。
投稿する項目が必須事項含め複数存在するので投稿には必然的にカスタムフィールドが存在します。

レシピを投稿すると、
カスタムフィールド『article』に、それぞれ
『レシピ名(recipe_name)』
『材料(material)』
『作り方(how_to_make)』
『コツ・注意点(notice_and_teck)』
『きっかけ(trigger)』
のカスタムフィールドに値が入る仕組みです。

検索を行うと、『レシピ名』『材料』『作り方』からキーワードが存在する投稿をloop式で表示します。ちなみに投稿順です。
しかし、『レシピ名』にキーワードがない投稿が上にきてしまうため少し見づらくなっています。

実現したいこと

「検索結果を、
カスタム投稿タイプ『article』の
カスタムフィールド『レシピ名(recipe_name)』に
『検索したキーワードが存在する投稿が上』になるように
並べ替えたい。
その上で、カスタムフィールド『レシピ名』『材料』『作り方』でキーワードに該当する投稿も表示したい」

例えば、
「『レシピ名』にキーワードが存在する投稿 今日」
「『レシピ名』にキーワードが存在しない投稿 今日」
「『レシピ名』にキーワードが存在する投稿 昨日」
「『レシピ名』にキーワードが存在しない投稿 昨日」

のような感じです。

コード

検索結果画面のコードです。
search.php

  <div class="container">
    <p><?php the_search_query(); ?>」の検索結果</p>
    <div class="flexer">
      <ul class="panel recipe_list">
        <?php
          $args_ct = array(
          'post_type' => 'article',
          'post_status' => 'publish',
          'posts_per_page' => 6,
          );
          $the_query_ct = new WP_Query($args_ct);

         ?>
        <?php if($the_query_ct->have_posts()): ?>
           --- 略 ---
          <?php while($the_query_ct->have_posts()): $the_query_ct->the_post();?>
            <?php get_template_part('template-parts/loop','article') ?>
          <?php endwhile; ?>
        <?php else: ?>
          <p>検索結果がありません</p>
        <?php endif; ?>
      </ul>

    </div><!--  .flexer -->
  </div><!--  .container -->


functions.phpの以下コードを使い、「検索対象をカスタム投稿タイプ『article』のカスタムフィールド『recipe_name』『material』『how_to_make』に限定する」処理をしています。

functions.php

       /* search.phpで検索する範囲を「特定のカスタムフィールド」に限定する */
       function custom_search($search, $wp_query) {
           global $wpdb;

           if (!$wp_query->is_search) return $search;
           if (!isset($wp_query->query_vars)) return $search;

           $search_words = explode(' ', isset($wp_query->query_vars['s']) ? $wp_query->query_vars['s'] : '');
           if ( count($search_words) > 0 ) {
               $search = '';
               $search .= "AND post_type = 'article'";
               foreach ( $search_words as $word ) {
                   if ( !empty($word) ) {
                       $search_word = '%'.esc_sql( $word ).'%';
                       $search .= " AND (
                {$wpdb->posts}.post_content LIKE '{$search_word}'
                           OR {$wpdb->posts}.ID IN (
                               SELECT distinct post_id
                               FROM {$wpdb->postmeta}
                               WHERE {$wpdb->postmeta}.meta_key IN ('recipe_name','material', 'how_to_make') AND meta_value LIKE '{$search_word}'
                           )
                       ) ";
                   }
               }
           }
           return $search;
       }
       add_filter('posts_search','custom_search', 10, 2);
// https://kazunori-miura.tumblr.com/post/189502558056/wordpress%E3%81%AE%E6%A4%9C%E7%B4%A2%E5%AF%BE%E8%B1%A1%E3%82%92%E7%89%B9%E5%AE%9A%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%AE%E5%80%A4%E3%81%AB%E9%99%90%E5%AE%9A%E3%81%99%E3%82%8B

このコードだけ見るなら、「$search .= 」からのSQLコードで「特定のカスタム投稿タイプ内のカスタムフィールド」を取得しているようです。

試したこと

調べてみると、「『本文(the_content)』に値がある投稿を優先して並べ替える」方法を見つけました。
このコードがヒントになると考えたのですが、応用ができないので挫折している最中です。

search.php?

$the_query = new WP_Query( array(
    'custom_orderby' => true,    // <-追加
) );


functions.php

function my_posts_orderby( $orderby, $query ) {
    global $wpdb;
    if ( $query->get( 'custom_orderby' ) ) {
        $orderby = "trim({$wpdb->posts}.post_content) = '' DESC, {$wpdb->posts}.post_date DESC";
    }
    return $orderby;
}
add_filter( 'posts_orderby', 'my_posts_orderby', 10, 2 );


具体的には、「カスタム投稿タイプ『article』のカスタムフィールド『recipe_name』の投稿」が取り出せるような応用ができていない状態です。

お時間をいただき、ありがとうございます。

補足情報(FW/ツールのバージョンなど)

ブラウザ:chrome(最新のバージョン)
テキストエディタ:atom(ver:1.32.2)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る