検索を実行する方法を探しています。検索の実行中に、「キーワード」という名前のカスタムフィールド、投稿のタイトル、および投稿の内容を確認します。これらのフィールドのいずれかに、ユーザーが検索したもののような結果がある場合は、結果ページにカスタムの投稿タイプ(プログラム)が表示されます。
最終的な表示結果については手助けは必要ありませんが(現在はやりたいことですが)、検索時に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;
}
まず、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_filter
をadd_filter
コールバックに追加して、それらを自動的に削除することもできます。