WordPressを拡張するという私の探求の次は、$sentence
変数が特定の基準を満たすときに、WordPressがposts_search
の$sentence
変数を使用して追加の文字列を含める方法を変更することです。
ここでの特定のユースケースは、誰かがTL123
のような何かをタイプするとき、TL-123
も検索するべきであるということです、ここでTL%
はここでのワイルドカードです。これは検索ミスを減らすためです(ハイフンを含まないもの)。
追加のSQLクエリを使ってposts_search
にフィルタする方法(これまでは実際に this one を使っています)を見たことがありますが、これがどのように機能するかについては少しあいまいです。任意の助けは大歓迎です。ありがとうございます。
編集 - @kaiserのおかげでニーズに関するより多くの情報を含めることができます
繰り返しますが、ここでのトリックは、一部の投稿にはTLではなくTLのみが含まれているため、追加の「部分フレーズ」も検索するためにそのパターンに一致する検索クエリを探している理由です。
ありがとうございます。
それでは、kaiserのスターター機能を基にして、次のことを思いつきました。
function wpse66815_search_query_string( $search, &$wp_query )
{
if (!is_admin() && is_search()) {
print_r($search);
global $wp_query;
// get search term
$search_term = array_shift($wp_query->query_vars['search_terms']);
// specify string we'll use to replace
$replace_var = 'TL';
// find matches for that string
preg_match_all("/{$replace_var}(?:[^0-9]*)(\d+)/i", $search_term, $out);
// if there's no matches, return the normal search
if ( empty($out[0]) )
return $search;
// find/generate the search term with the replacement
$modified_search_term = preg_replace("/{$replace_var}(?:[^0-9]*)(\d+)/i", "{$replace_var}-$1", $search_term);
// combine both the regular and modified search term
$new_search[] = $search_term;
$new_search[] = $modified_search_term;
//var_dump($new_search);
// generate the new search query
foreach ( $new_search as $keyword )
{
$new_string_parts[] = $GLOBALS['wpdb']->prepare(
"
AND ((%s.post_title LIKE '%%%s%%') OR (%s.post_content LIKE '%%%s%%'))
"
,"{$GLOBALS['wpdb']->prefix}posts"
,like_escape( $keyword )
,"{$GLOBALS['wpdb']->prefix}posts"
,like_escape( $keyword )
);
}
// set $search equal to results
$search = implode( " ", $new_string_parts );
//print_r($search);
}
return $search;
}
add_filter('posts_search', 'wpse66815_search_query_string',500,2);
私が乗り越えることができない部分は、実際には実際のSQLクエリです - >下記のエラーです。
WordPress database error: [You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.post_title LIKE 'tl123') OR ('wp__posts'.post_content LIKE 'tl123')) ' at line 2]
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND (('wp__posts'.post_title LIKE 'tl123') OR ('wp__posts'.post_content LIKE 'tl123')) AND (('wp__posts'.post_title LIKE 'TL-123') OR ('wp__posts'.post_content LIKE 'TL-123')) AND wp_posts.post_type IN ('post', 'page', 'attachment', 'galleries', 'idea_gallery', 'moulding_profiles', 'moulding_collection', 'moulding_combination') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 2 AND wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 80
どこに問題があったのかについての質問はありますか。ありがとうございます。
私はいくつかの問題を見始めました:
wp__posts
の代わりにwp_posts
をしていました(私はそれを上で更新しました)kaiser
が述べたように、LIKE %s
部分はLIKE %%s%
である必要があるかもしれませんが、それは正しく構文解析されていません。エラーは今です:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND (('wp_posts'.post_title LIKE 'tl123') OR ('wp_posts'.post_content LIKE 'tl123')) AND (('wp_posts'.post_title LIKE 'TL-123') OR ('wp_posts'.post_content LIKE 'TL-123')) AND wp_posts.post_type IN ('post', 'page', 'attachment', 'galleries', 'idea_gallery', 'moulding_profiles', 'moulding_collection', 'moulding_combination') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 2 AND wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 80
上のエラーは(私が言うことができるものから)実際にはtl123
とTL-123
の両方である投稿を探すことですが、私はOR
が私が欲しいものであると思います(どちらかの状況で投稿を返したいので)。
%s
を正しくエスケープするように関数を更新しました。エラーは次のようになりました。
WordPress database error: [You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.post_title LIKE '%tl123%') OR ('wp_posts'.post_content LIKE '%tl123%')) ' at line 2]
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND (('wp_posts'.post_title LIKE '%tl123%') OR ('wp_posts'.post_content LIKE '%tl123%')) AND (('wp_posts'.post_title LIKE '%TL-123%') OR ('wp_posts'.post_content LIKE '%TL-123%')) AND wp_posts.post_type IN ('post', 'page', 'attachment', 'galleries', 'idea_gallery', 'moulding_profiles', 'moulding_collection', 'moulding_combination') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 2 AND wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 80
これが私がやることになったものです - > foreachは(@kaiserが述べたようにAND/OR演算子で)正しくラッピングしていなかったので、私はそれらをそれら自身の配列挿入に分けました。
function wpse66815_search_query_string( $search, &$wp_query )
{
if (!is_admin() && is_search()) {
//print_r($search);
global $wp_query,$wpdb;
// get search term
$search_term = array_shift($wp_query->query_vars['search_terms']);
// specify string we'll use to replace
$replace_var = 'TL';
// find matches for that string
preg_match_all("/{$replace_var}(?:[^0-9]*)(\d+)/i", $search_term, $out);
// if there's no matches, return the normal search
if ( empty($out[0]) )
return $search;
// find/generate the search term with the replacement
$modified_search_term = preg_replace("/{$replace_var}(?:[^0-9]*)(\d+)/i", "{$replace_var}-$1", $search_term);
// combine both the regular and modified search term
$new_search[] = $search_term;
$new_search[] = $modified_search_term;
var_dump($new_search);
// generate the new search query
$new_string_parts[] = $wpdb->prepare( "AND ((({$wpdb->posts}.post_title LIKE '%%%s%%') OR ({$wpdb->posts}.post_content LIKE '%%%s%%'))",like_escape( $new_search[0] ),like_escape( $new_search[0] ));
$new_string_parts[] = $wpdb->prepare( "OR (({$wpdb->posts}.post_title LIKE '%%%s%%') OR ({$wpdb->posts}.post_content LIKE '%%%s%%')))",like_escape( $new_search[1] ),like_escape( $new_search[1] ));
// set $search equal to results
$search = implode( " ", $new_string_parts );
//print_r($search);
}
return $search;
}
add_filter('posts_search', 'wpse66815_search_query_string',500,2);
誰かがtl123 tl456
(tl
キーワードが2回出現する)を入力しようとした場合、それはいくつかの問題を抱えていますが、私はその部分に取り組んでいます。ありがとうございます。
昨日その日のために2つのプラグインを作成しました。
これが、検索クエリ部分がposts_search
フィルタ内でどのように見えるかです。
' AND (((wp_XX_posts.post_title LIKE '%test%') OR (wp_XX_posts.post_content LIKE '%test%'))) '
ここでwp_XX_
は私のローカルMUインストール内の私のWPSEテストサイト用の$wpdb->prefix
です。
これは頻繁に必要とされるので、これは検索された投稿タイプを修正するプラグインです。
<?php
/** Plugin Name: (#66815) »kaiser« Limit search query post types */
/**
* Alter the searched post types
*
* @param object $query
* @return object $query
*/
add_action( 'pre_get_posts', 'wpse66815_pre_get_posts' );
function wpse66815_pre_get_posts( $query )
{
if ( $query->is_main_query() )
{
$query->set( 'post_type', 'YOUR_POST_TYPE' );
}
return $query;
}
これで、投稿のタイトルとコンテンツのデフォルトの検索文字列がどのように見えるかがわかったので、必要な方法でそれを再構築する必要があります。
<?php
/** Plugin Name: (#66815) »kaiser« Modify search query string */
function wpse66815_search_query_string( $search_string )
{
global $wpdb;
$searched_for = preg_match_all(
// Match a prefix (%), but exclude it from the capture
// Any character, any number of repetitions
// Match a suffix (%), but exclude it from the capture
"/(?<=\%)(.*)(?=\%)/",
$search_string,
$search_string_matches
);
// We only need one element
$searched_for = array_shift( $search_string_matches );
// Now we need to search for [LETTERS (min 1)][NUMBER (zero or more)][CHARACTER (zero or more)]
preg_match_all(
"/([^a-zA-Z][\d+]*[-_ ]*)/",
$searched_for,
$string_part_matches
);
// Here we now got matches - if not, we can simply abort and leave the default
$searched_for = array_shift( $string_part_matches );
if ( empty( $searched_for ) )
return $search_string;
// Finally we need to split the string by all parts that are allowed
// YOU NEED TO EDIT MY ANSWER HERE AND FILL IN WHAT WORKS FOR YOU
$keywords = preg_split(
"/([\s]*[\d+]*[-_ ]*)/",
$searched_for,
-1, // 0 & -1 are NO limit
PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE
);
// Now loop and build an array for further processing
// Our first search string is - of course - the default string
$string_parts = array( $search_string );
foreach ( $keywords as $keyword )
{
$new_string_parts[] = $GLOBALS['wpdb']->prepare(
" AND ((%s.post_title LIKE '%s') OR (%s.post_content LIKE '%s')) ",
$wpdb->posts,
$wpdb->esc_like( $keyword ),
$wpdb->posts,
$wpdb->esc_like( $keyword )
);
}
// Now lets glue them together, return and see what we get...
return implode( " ", $new_string_parts );
}
この2nd プラグインはテストされていません、私のニーズは異なっていて、正規表現のいくつかは完全にあなたが必要としているものではないと思いますA)私が見つけた正規表現を構築するための素晴らしいツールは Expresso です。それは(ウェブの存在として)醜いものですが、非常に役に立ちます。