WordPressのタクソノミー検索をカスタマイズする
Posted by admin at 13:46 日時 2013/11/17
時々WordPressコミュニティの人に「WordPressとconcrete5の使い分けをどうしてるのか?」と聞かれるのですが、内心では「WordPressのタクソノミーはマジ便利なのでタクソノミーを使う場合はWordPress、WordPressのカスタムフィールドは不便なのでconcrete5の方がいい」と思ってるのですが、細かい話になるのでそこまでは言わないのですが、実例をひとつ。
映画データベースのサイトを作る際に、カスタムタクソノミーに「Actors」を追加し、俳優の名前をタームとして登録していくプランを考えてみましょう。ジェイソン・ステイサムの検索結果がこちら。スナッチとトランスポーターが登録されています。
続いてブラッド・ピットの検索結果です。ファイトクラブとスナッチが表示されます。
さて、ジェイソン・ステイサムとブラッド・ピットを両方検索パラメーターに付けるとどうなるか。
ジェイソン・ステイサムとブラッド・ピットのどちらかが出演している映画が表示されます。ここまで、インストール直後の状態にカスタムタクソノミーを追加しただけです。一切カスタマイズしていません。これでOKな仕様なら、WordPressで作るのが圧倒的にラクチンです。
ところで、ジェイソン・ステイサムとブラッド・ピットの両方が出演している映画を表示したい場合はちょっと工夫が必要です。「parse_tax_query」アクションフックを使いましょう。
function mod_tax_query( $the_query ) { // $the_query は WP_Query のインスタンス if ($the_query->is_main_query()) { // メインクエリー中の WP_Tax_Query を取得 $_tax_query = $the_query->tax_query; $_queries = array(); if ($_tax_query instanceof WP_Tax_Query) { foreach ($_tax_query->queries as $query) { // 目的のタクソノミーだった場合に if ($query['taxonomy'] == 'actors') { // オペレーターを変更 $query['operator'] = 'AND'; } $_queries[] = $query; } // メインクエリーに改変した WP_Tax_Query を戻す $_tax_query->queries = $_queries; $the_query->tax_query = $_tax_query; } unset($_queries); unset($_tax_query); } } add_action( 'parse_tax_query', 'mod_tax_query' );
Taxonomy Queryの ‘operator’ パラメーターの初期値は ‘IN’ なので、これを ‘AND’ に変更しています。
Codex: WP_Query # Taxonomy Parameters
この通り。タクソノミーを使う用事が予見されるとWordPressを使うのが楽です。
追記:カンマ区切り使いにくいやろが
上記のように、WordPressは複数のタームを受け取る際にカンマ区切り、または “+” で区切る仕様になっていますが、実際のところチェックボックスでインターフェースを作ると ?actors[]=brad-pitt&actors[]=jason-statham のようなURLになると思います。この場合actorsパラメーターの値は配列になりますが、なんとWordPressは配列を受け取るとエラーになるので、、、parse_requestフックで+区切りなどに変更してあげないといけません。
function mod_parse_request( $wp ) { $actors = $_REQUEST['actors']; if(isset($actors) && is_array($actors)) { $actors = implode('+', $actors); $wp->set_query_var('actors',$actors); } } add_action('parse_request', 'mod_parse_request');
追記の追記:で、検索インターフェースはどうやって作るねん
特別サービスや!持って行き!
<form action="<?php echo home_url(); ?>" method="get"> <ul> <?php $terms = get_terms(array('actors')); foreach($terms as $term){ $checked = (is_array($_REQUEST['actors'])) ? checked(in_array($term->slug, $_REQUEST['actors']), true, false) : ''; echo sprintf( '<li><label><input type="checkbox" name="%s[]" value="%s" %s/>%s</label></li>', $term->taxonomy, $term->slug, $checked, $term->name ); } ?> </ul> <input type="submit" value="検索" /> </form>