1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Wordpressのカスタム投稿をキーワード検索に含める処理

Posted at

※この投稿は、
Wordpress、ACF(Advanced Custom Fields)、カスタムフィールド、カスタム投稿、pre_get_posts
この辺りのキーワードに関する記事です。

<やりたいこと>
WordpressのACFで作成した病院の施設情報の(施設名、住所、診療科)を、カスタム投稿で何件か作成して、pre_get_postsの書き方で表示する。
チェックボックスと、フリーのキーワード検索の機能を追加して、検索結果も表示する。
例えば、、、
キーワード検索の欄に、"長崎県"と入力→住所が長崎県の施設を取得
チェックボックスに”消化器内科”、キーワード検索の欄に"長崎県"と入力→長崎県にある消化器内科がある施設を取得

ACFの参考サイト
https://usagicode.com/wordpress/how-to-use-advanced-custom-fields/

<環境>
wordpressのプラグインACFを使用

post_type:hospitals
病院名:投稿のタイトル
住所:カスタムフィールドの名前(hospital_address)
診療科:カスタムフィールドの名前(hospital_medical)
スクリーンショット 2024-02-28 16.11.48.png

<挙動>
Index.phpで検索の画面
スクリーンショット 2024-02-28 16.12.34.png


functions.phpを通してarchive.phpへ

archive.phpで
病院名、住所、診療科目の表示
↓"クリニック"とキーワード検索したときの画面
スクリーンショット 2024-02-28 16.13.02.png

ちなみに、、、、
初めは、archive.phpで検索画面と検索結果のどちらも表示していた。
(archive.phpで検索して、結果もarchive.phpで表示)
検索した時に、該当のデータの数は取れるが、中身がちゃんと表示されていない状況

検索画面と検索結果の画面を分けた → うまく表示されるようになった。

<コード一覧>
・index.php

<h2>診療科目選択</h2>

<!-- 検索フォーム -->
<form role="search" method="get" id="searchform" class="searchform" action="<?php echo esc_url(home_url('/hospitals')); ?>">
  <?php
  // 全ての施設情報を取得
  $posts = get_posts(
    array(
    'post_type' => 'hospitals',
    'posts_per_page' => -1,
  )
);
  $specialities = array(); // 診療科目を保存する配列

  foreach ($posts as $post) {  // 取得した投稿をループ処理
    $specialities_array = get_field('hospital_medical', $post->ID); //診療科目を取得

    if (is_array($specialities_array)) {
      foreach ($specialities_array as $item) {
        if (!in_array($item, $specialities)) { // 診療科目がまだ配列に追加されていなければ追加
          $specialities[] = $item;
        }
      }
    }
  }

  // 診療科目のチェックボックスを表示
foreach ($specialities as $item) {
  // チェックされた値を取得
  $checked = '';
  if (isset($_GET['specialities_array']) && in_array($item, $_GET['specialities_array'])) {
      $checked = ' checked="checked"';
  }
    echo '<input type="checkbox" name="specialities_array[]" value="' . esc_attr($item) . '">' . esc_html($item) . '<br>';
  }
  ?>
  <div>
    <label class="screen-reader-text" for="s"><?php _x('Search for:', 'label'); ?></label>
    <input type="text" value="<?php echo get_search_query(); ?>" name="s" id="s" placeholder="キーワード検索">
    <input type="submit" id="searchsubmit" value="検索">
    <a href="<?php echo esc_url(home_url('hospitals/')); ?>">リセット</a>
  </div>
</form>
<!-- 検索フォームここまで -->

・archive.php

<h2>検索結果</h2><br>
<!-- アーカイブ表示 -->
<?php
// アーカイブページのメインループ
  if(have_posts()){
    while ( have_posts() ) : the_post();?>
        <!-- // タイトル表示 -->
        <h2><?php the_title(); ?></h2>
        <p>住所:<?php the_field('hospital_address'); ?></p>
        <p>診療科目:<?php the_field('hospital_medical'); ?></p>
        <?php echo '<hr>';
    endwhile;
    echo paginate_links();
  } else {
    echo "記事なし";
  }
?>
<br>
<a href="<?php echo esc_url(home_url('/')); ?>">検索画面へ</a>

・functions.php

<?php
//サイト内検索の設定
add_filter('pre_get_posts', 'filter_search');
function filter_search($query)
{
    if ( is_admin() && !$query->is_main_query() ){
        return;
    }
    if ($query->is_search()) {
        $query->set('post_type', 'hospitals');
        $page = get_query_var('paged') ? get_query_var('paged') : 1;
        
        $query->set('paged', $page);
        $query->set( 'posts_per_page', -1 );
    }
}

// 検索
add_filter('posts_search', 'custom_search', 10, 2);
function custom_search($search, $wp_query)
{
    global $wpdb;
    if (!$wp_query->is_archive) {
        return $search;
    }
    if (!isset($wp_query->query_vars)) {
        return $search;
    }

    $search_words =  isset($wp_query->query_vars['s']) ? $wp_query->query_vars['s'] : "";
    
    $search_words = explode(' ', $search_words);
    // タイトル検索用のSQLを構築
    if (count($search_words) > 0) {
        $search = '';
            $search .= " AND post_type = 'hospitals' ";
            foreach($search_words as $search_word ) {
                if (!empty($search_word)){
                    $search_word = '%'. esc_sql($search_word) .'%';
                    // var_dump($search_word);

                    $search .= " AND ({$wpdb->posts}.post_title LIKE '{$search_word}' 
                    OR {$wpdb->posts}.ID IN ( 
                        SELECT distinct post_id 
                        FROM {$wpdb->postmeta} 
                        WHERE meta_value LIKE '{$search_word}') 
                    )";
                }
            }
        }
    return $search;
}
?>

<?php
function filter_hospital_query( $query ) {

    //is_admin() をチェックして管理画面のクエリには影響ないようにする
    //$query->is_main_query() でメインクエリであることをチェック
    if ( is_admin() && !$query->is_main_query() ){
        return;
    }
    if ($query->is_archive) {

        $query->set('post_type', 'hospitals');

        $page = get_query_var('paged') ? get_query_var('paged') : 1;

        $meta_query = array();
        // var_dump($meta_query);

        $selected_specialities = isset( $_GET['specialities_array'] ) ? $_GET['specialities_array'] : array();
            // var_dump($selected_specialities);
        
            // チェックボックスのみの時
        if ( $selected_specialities && empty($search_term) ) {
            foreach ( $selected_specialities as $selected ) {

                $meta_query[] = array(
                    'key'     => 'hospital_medical',
                    'value'   => $selected,
                    'compare' => 'LIKE',
                );
            }
            $query->set('paged', $page);
            $query->set( 'posts_per_page', -1 );
            $query->set( 'meta_query', $meta_query );
        }
    }
}
add_action( 'pre_get_posts', 'filter_hospital_query' );
?>

参考サイト

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?