WordPressのカスタム投稿タイプ作成+カテゴリ検索+文字列検索(カスタムフィールド含む)+ページネーションの実装
やりたいこと
タイトルのママ。
カスタム投稿タイプでカテゴリ(taxonomy)+文字列検索(?s=hogehoge)、ページャーを実装したい
URL的にこんな感じ
http://xxxxxx.jp/topics/?topics_cat=asia&s=
→アジアのカテゴリのものが一覧で全部出てくる
http://xxxxxx.jp/topics/?topics_cat=asia&s=お茶
→アジアのカテゴリの中でお茶のものが出てくる
http://xxxxxx.jp/topics/?topics_cat=soup&s=
→カテゴリに属するものだけが出てくる(普通にPOSTのループでまわせばカテゴリajiaのものだけが紐付いてくれるので自分でわざわざクエリ作ったりしなくていい。ひとつのテンプレートファイルでOK)
今回の例
カスタム投稿タイプ:topics
タクソノミー:topics_cat
カテゴリ:アジア、日本
この場合、必要なテンプレートファイルは下記のように対応する。
カスタム投稿タイプに属する投稿の一覧表示 → archive-topics.php (ここにフォーム設置)
カスタム投稿タイプに属するカテゴリの一覧 → taxonomy-topics_cat.php
カスタム投稿タイプに属する投稿 → single-topics.php
カスタム投稿タイプに属する投稿の検索 → topics-search.php(ここにもフォーム設置)
実際のコード
topics-search.php
<div id="search"> <form method="get" action="/topics/"> <?php $args = array( 'taxonomy' => 'topics_cat', 'name' => 'topics_cat', 'depth'=>'0', 'orderby' => 'name', 'hide_empty' => '1', 'show_option_all' => 'カテゴリ(任意)', 'value_field' => 'slug' ); wp_dropdown_categories($args); ?> <?php $tags = get_tags();?> <?php if ( $tags ) ://複数検索の場合? ?> <select name='tag' id='tag'> <option value="" selected="selected">タグ選択</option> <?php foreach ( $tags as $tag ): ?> <option value="<?php echo esc_html( $tag->slug); ?>"><?php echo esc_html( $tag->slug ); ?></option> <?php echo $tag->slug;?> <?php endforeach; ?> </select> <?php endif; ?> <input name="s" id="s" type="text" placeholder="キーワード(材料・レシピ名)" /> <input id="submit" type="submit" value="検索する" /> </form> </div>
function.php
/* 投稿タイプを追加 */
add_action( 'init', 'create_post_type' );
function create_post_type() {
register_post_type( 'topics', //投稿タイプ名を指定
array(
'labels' => array(
'name' => __( 'TOPICS' ),
'all_items' => '投稿一覧',
'singular_name' => __( 'TOPICS' ),
'parent' => '親'
),
'public' => true,
'has_archive' => true, /* アーカイブページを持つ */
'menu_position' =>4, //管理画面のメニュー順位
'supports' => array( 'title', 'author' ),
'taxonomies' => array('topics_cat'),
)
);
register_taxonomy(
'topics_cat', /* タクソノミーの名前 */
'topics', /* 使用するカスタム投稿タイプ名 */
array(
'hierarchical' => true,
'update_count_callback' => '_update_post_term_count',
'label' => 'カテゴリー',
'singular_label' => 'カテゴリー',
'public' => true,
'show_ui' => true,
'publicly_queryable' => true,
'has_archive' => true,
'rewrite' => array( 'slug' => 'category' ),
'query_var' => true
)
);
};
//カスタム投稿用post_typeセット
add_filter('template_include','custom_search_template');
function custom_search_template($template){
if ( is_search() ){
$post_types = get_query_var('post_type');
foreach ( (array) $post_types as $post_type )
$templates[] = "{$post_type}-search.php";
$templates[] = 'search.php';
$template = get_query_template('search',$templates);
}
return $template;
}
//標準検索機能にカスタムフィールドを含める
function custom_search($search, $wp_query) {
global $wpdb;
if (!$wp_query->is_search)
return $search;
if (!isset($wp_query->query_vars))
return $search;
$search_words = explode(' ', isset($wp_query->query_vars['s']) ? $wp_query->query_vars['s'] : '');
if ( count($search_words) > 0 ) {
$search = '';
$search .= "AND post_type = 'post'"; //ここは適宜変更
foreach ( $search_words as $word ) {
if ( !empty($word) ) {
$search_word = '%' . esc_sql( $word ) . '%';
$search .= " AND (
{$wpdb->posts}.post_title LIKE '{$search_word}'
OR {$wpdb->posts}.post_content LIKE '{$search_word}'
OR {$wpdb->posts}.ID IN (
SELECT distinct post_id
FROM {$wpdb->postmeta}
WHERE meta_value LIKE '{$search_word}'
)
) ";
}
}
}
return $search;
}
add_filter('posts_search','custom_search', 10, 2);
/**
* ページネーション出力関数
* $paged : 現在のページ
* $pages : 全ページ数
* $range : 左右に何ページ表示するか
* $show_only : 1ページしかない時に表示するかどうか
*/
function pagination( $pages, $paged, $range = 2, $show_only = false ) {
$pages = ( int ) $pages; //float型で渡ってくるので明示的に int型 へ
$paged = $paged ?: 1; //get_query_var('paged')をそのまま投げても大丈夫なように
//表示テキスト
$text_first = "« 最初へ";
$text_before = "前へ";
$text_next = "次へ";
$text_last = "最後へ »";
if ( $show_only && $pages === 1 ) {
// 1ページのみで表示設定が true の時
echo '<div class="pagination"><span class="current pager">1</span></div>';
return;
}
if ( $pages === 1 ) return; // 1ページのみで表示設定もない場合
if ( 1 !== $pages ) {
//2ページ以上の時
echo '<nav class="pagination"><!--<span class="page_num">Page ', $paged ,' of ', $pages ,'</span>--><div class="nav-links">';
if ( $paged > $range + 1 ) {
// 「最初へ」 の表示
//echo '<a href="', get_pagenum_link(1) ,'" class="first">', $text_first ,'</a>';
}
if ( $paged > 1 ) {
// 「前へ」 の表示
echo '<a href="', get_pagenum_link( $paged - 1 ) ,'" class="prev page-numbers">', $text_before ,'</a>';
}
for ( $i = 1; $i <= $pages; $i++ ) {
if ( $i <= $paged + $range && $i >= $paged - $range ) {
// $paged +- $range 以内であればページ番号を出力
if ( $paged === $i ) {
echo '<span class="page-numbers current">', $i ,'</span>';
} else {
echo '<a href="', get_pagenum_link( $i ) ,'" class="page-numbers">', $i ,'</a>';
}
}
}
if ( $paged < $pages ) {
// 「次へ」 の表示
echo '<a href="', get_pagenum_link( $paged + 1 ) ,'" class="next page-numbers">', $text_next ,'</a>';
}
if ( $paged + $range < $pages ) {
// 「最後へ」 の表示
//echo '<a href="', get_pagenum_link( $pages ) ,'" class="last">', $text_last ,'</a>';
}
echo '</div></nav>';
}
}
今回ハマったポイント
・文字列検索だけだとできるけどカテゴリを含めると何も出てこなかった。
→下記のサイトにも記載されていたが、
wp_dropdown_categoriesをつかって、
taxonomyでタクソノミー(カスタム投稿カテゴリ)のスラッグを指定するのは必須。nameとvalue_fieldについては、「?タクソノミースラッグ名=タームスラッグ名」としないとうまいこと検索が動かなかったための設定です。
これが全てだった。。
参考サイト https://www.islog.jp/entry/wp_dropdown_categories/
あとカテゴリーのテンプレート名がわからなかった。
taxonomy-topics_cat.phpてやつ。
わかってしまえばなんてこと無いが、やはりググり力は大事。