Last active
February 22, 2017 02:48
-
-
Save SapporoTK/724ec1341f82435242fb4c9f47135b23 to your computer and use it in GitHub Desktop.
WordPress + Custom Fields に複雑な検索機能を実装する。/reference http://www.deluxeblogtips.com/2012/04/search-all-custom-fields.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
global $wpdb; | |
//次のSQLに SQL_CACHE を含めているのは、レンタルサーバーによってはMySQLのクエリキャッシュの | |
//デフォルト設定を無効にしているところがあるので、明示的にクエリキャッシュを有効にするように指定している。 | |
$sql = "SELECT SQL_CACHE DISTINCT posts.ID FROM {$wpdb->posts} posts"; | |
//チェックボックスorセレクトボックスの検索(複数のAND検索) | |
//例えばcolorというフィールド名だとする。 | |
//$_GET['color']にはカスタムフィールドの設定画面の選択肢の箇所で入力したラベルと値のうち、値の方が配列になって入ってくるとする。 | |
if( count($_GET['color']) ) | |
{ | |
$flg_query = true; | |
$sql .= " INNER JOIN {$wpdb->postmeta} tbl_color ON tbl_color.post_id=posts.ID AND tbl_color.meta_key = 'color'"; | |
$tmp_arr = array(); | |
foreach ($_GET['color'] as $item) | |
{ | |
//シリアライズ化された文字列の中を全文検索する | |
$keyword = '%' . $wpdb->esc_like( '"' . trim($item) . '"' ) . '%'; | |
$tmp_arr[] = "tbl_color.meta_value LIKE '{$keyword}'"; | |
} | |
$sql .= " AND (" . implode(" AND ", $tmp_arr) . ") "; | |
//↓ちなみにOR検索の場合はこうする | |
//$sql .= " AND (" . implode(" OR ", $tmp_arr) . ") "; | |
} | |
//複数のチェックボックスorセレクトボックスがある場合は、ここに追記していく。 | |
//注意点として、選択肢の値を 1,2,3・・や a,b,c・・のように設定すると | |
//他のフィールドと値が重複して正確な検索が出来ないので、全フィールドを通じてユニークな値にする必要がある。 | |
$sql .= " WHERE posts.post_type='(※投稿タイプ名※)' AND posts.post_status='publish'"; | |
//全文検索(AND検索) | |
//全文検索用キーワード | |
//$_GET['keyword']にはキーワードが半角スペース区切りで入っているとする。 | |
$free_keyword = isset($_GET['keyword']) ? trim($_GET['keyword']) : ""; //「キーワード検索」 | |
if( $free_keyword != "" ) | |
{ | |
$arr_free_keyword = $free_keyword == "" ? array() : explode(" ", $free_keyword); | |
$arr_free_keyword = array_unique($arr_free_keyword); | |
if( count($arr_free_keyword) > 8 ) | |
{ | |
//検索キーワード数の上限をとりあえず8個までにする。 | |
//ここが無制限だと、意図的に膨大なキーワード数で検索を実行された時にサーバーの処理が追いつかなくなる危険性が生じるので。 | |
$arr_free_keyword = array_slice($arr_free_keyword, 0, 8); | |
} | |
$tbl_cnt = 1; | |
foreach ($arr_free_keyword as $_key) | |
{ | |
$tbl = "key" . $tbl_cnt++; | |
$keyword = '%' . $wpdb->esc_like( trim($_key) ) . '%'; | |
$sql .= " AND (SELECT 1 FROM {$wpdb->postmeta} {$tbl} WHERE {$tbl}.post_id=posts.ID AND ( ({$tbl}.meta_key NOT LIKE '\_%' AND {$tbl}.meta_value LIKE '{$keyword}') OR posts.post_title LIKE '{$keyword}' OR posts.post_content LIKE '{$keyword}') LIMIT 1)"; | |
//↑DISTINCTにしてもいいのだが、LIMIT 1 の方が速度が早いと思われるので(ただし未検証) | |
} | |
} | |
$post_ids = $wpdb->get_col($sql); //検索でヒットした投稿データのIDが入る | |
$cnt = count($post_ids); //投稿数 | |
if($cnt) | |
{ | |
$args = array( | |
'post_type' => '(※投稿タイプ名※)', | |
'post_status' => 'publish', | |
'post__in' => $post_ids, | |
//ページングする場合は次のパラメーターをお好みで | |
'posts_per_page' => ****, | |
'offset' => ***, | |
//ソートする場合は 次のパラメーターをお好みで | |
'meta_key' => '******', | |
'order' => "ASC", /* or DESC */ | |
'orderby' => "meta_value" | |
); | |
$posts = get_posts($args); | |
} | |
else | |
{ | |
$posts = array(); | |
} | |
以下略 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment