web-dev-qa-db-ja.com

カスタムフィールド、投稿タイトル、投稿コンテンツを検索する検索

検索を実行する方法を探しています。検索の実行中に、「キーワード」という名前のカスタムフィールド、投稿のタイトル、および投稿の内容を確認します。これらのフィールドのいずれかに、ユーザーが検索したもののような結果がある場合は、結果ページにカスタムの投稿タイプ(プログラム)が表示されます。

最終的な表示結果については手助けは必要ありませんが(現在はやりたいことですが)、検索時に3つのフィールド(投稿タイトル、投稿コンテンツ、カスタムフィールドキーワード)すべてをチェックするようにする必要がありますそしてそれらのどれかが検索されたもののような結果を持っていれば、それは結果を表示します。これは私が今まで持っているコードです。現在はキーワードのカスタムフィールドのみを検索しています。

elseif($program_search) {
    // search by program search text
    query_posts(array(
    'post_type' => 'program',
    'meta_query' => array(
        array(
            'key' => 'keywords',
            'value' => $program_search,
            'compare' => 'LIKE'
        ),      
    )
    ));             
    if ( have_posts() ) : 
        while ( have_posts() ) : 
            the_post();
            $l.= "<div class='program-item'>";
                $l.= "<div class='program-item-image'><a href='".get_permalink($post->ID)."'>". get_the_post_thumbnail($post->ID, 'thumbnail')."</a></div>";
                $l.= "<div class='program-item-title'><a href='".get_permalink($post->ID)."'>".get_the_title($post->ID)."</a></div>";
                $l.= "<div class='program-item-content'>".get_the_excerpt()."</div>";
                $l.= "<div style='clear:both;'></div>";
            $l.= "</div>";
         endwhile; 
    else:
    endif;
}
4
Brandon

まず、query_postsを使わないでください。

次に、sパラメータを渡して、そこにほとんどの方法でアクセスできます。

$program_search = 'test';
$args = array(
  'post_type' => 'program',
  's' => $program_search,
  'meta_query' => array(
    array(
      'key' => 'keywords',
      'value' => $program_search,
      'compare' => 'LIKE'
    ),      
  )
);
$t = new WP_Query($args);
var_dump($t->request);

そのsパラメータは、通常の検索メカニズムを適切な場所に配置し、タイトルとコンテンツが検索されます。あなたがその生成されたクエリを見ればあなたが見るでしょう...

SELECT 
  SQL_CALC_FOUND_ROWS 
  wp_posts.ID 
FROM wp_posts 
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id) 
WHERE 1=1 
AND (((wp_posts.post_title LIKE '%test%') OR (wp_posts.post_content LIKE '%test%'))) 
AND (wp_posts.post_password = '') 
AND wp_posts.post_type = 'program' 
AND (wp_posts.post_status = 'publish') 
AND ((wp_postmeta.meta_key = 'keywords' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%test%')) 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.post_date DESC 
LIMIT 0, 5

それはあなたが望むもののほとんどです。特に指定のない限り、LIMITは、wp-admin-> Settings-> Generalで設定されている制限です。しかし問題があります。

AND ((wp_postmeta.meta_key = 'keywords' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%test%')) 

私はあなたがそれをOR ((wp_postmeta.meta_key ...にしたいこと、そしてあなたが本当にそれをpost_titleおよびpost_contentと一緒にしたいことを確信しています。このようなもの:

AND (
  (
    (wp_posts.post_title LIKE '%test%') 
    OR 
    (wp_posts.post_content LIKE '%test%')
    OR 
    (wp_postmeta.meta_key = 'keywords' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%test%')
  )
) 

WP_Queryはそれをしないでしょう、それで我々はいくつかのフィルタでそれをしなければなりません。コンセプトの証明:

function add_join_wpse_99849($joins) {
  global $wpdb;
  return $joins . " INNER JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id)";
}

function alter_search_wpse_99849($search,$qry) {
  global $wpdb;
  $add = $wpdb->prepare("({$wpdb->postmeta}.meta_key = 'keywords' AND CAST({$wpdb->postmeta}.meta_value AS CHAR) LIKE '%%%s%%')",$qry->get('s'));
  $pat = '|\(\((.+)\)\)|';
  $search = preg_replace($pat,'(($1 OR '.$add.'))',$search);
  return $search;
}

$program_search = 'test';
$args = array(
  'post_type' => 'program',
  's' => $program_search
);

add_filter('posts_join','add_join_wpse_99849');
add_filter('posts_search','alter_search_wpse_99849',1,2);
$t = new WP_Query($args);
remove_filter('posts_join','add_join_wpse_99849');
remove_filter('posts_search','alter_search_wpse_99849',1,2);

// dump some data
var_dump($t->request);
var_dump($t->posts);

私はmeta_queryを完全に省き、機能を大部分複製したことに注意してください。これは、厄介なANDが生成されないようにするためです。

他のクエリに干渉しないように、これらのフィルタを適用してすぐに削除します。フィルタを邪魔にならないようにする他の方法や他のクエリがあります。 そのような方法のひとつがここで概説されていますremove_filteradd_filterコールバックに追加して、それらを自動的に削除することもできます。

11
s_ha_dum