tips

複数タクソノミーで絞り込めるアーカイブページを作成する。

wordpressで複数タクソノミによるPOSTの絞り込みの方法はそちこちで紹介されています。(個人的にはここが参照しやすいと思う。)こいつを、従来のカテゴリページのようにページングができる複数タクソノミのアーカイブページとして設置したい、というわけです。
multiple_tax

 

パーマリンクがないからパラメータでURLをカスタマイズする

例えばポストに次のような2種類のカスタムタクソノミを割り当てているとします。

taxonomy: color   terms: red / blue / green

taxonomy: form   terms: square / circle / triangle

普通にタクソノミーのテンプレートでは
//example.com/color/red
…とか
//example.com/form/square/page/2
…とかは表示できても、colorはredかつformはsquareみたいにできない。そもそもそんなパーマリンクが存在しないのだから、ページングできるわけがない。この問題を回避するためにURLクエリパラメータを与えることにします。
最終的なURLは
//example.com/items?color=red&form=square
…とか
//example.com/items/page/2?color=blue&form=circle
…のような感じになります。googleさんの検索結果ページと一緒ですね。

 


 

設置の順序

① まずはカスタムタクソノミを作ります。

カスタムタクソノミを$postかカスタム投稿タイプに割り当てます。(まずそこからという方はこちらとかを参照して下さい。)

② アーカイブページの代わりにするための固定ページを作成

自動的に作られるアーカイブページの代わりに適当な名前の固定ページを作成し、適当なページ用のテンプレートphpを用意します。(今ひとつ意味が分からない方はこちらとかが参考になるかもしれません。)WP_Queryを使ってカスタム投稿タイプのアーカイブを表示します。(※以下ではカスタム投稿タイプは「item」、固定ページのslugは「items」と設定したものとして表記していきます。)

<?php
	$args = array(
		'post_type' => 'item',
	);
	$wp_query = new WP_Query();
	$wp_query->query( $args );
	$li = '';
	while ( $wp_query->have_posts() ) : $wp_query->the_post(); 
?>
<div class="post">
	<a href="<?php echo get_permalink( $post->ID );?>" title="<?php echo get_the_title( $post->ID );?">
		<h2><?php the_title( ); ?></h2>
		<div class="excerpt"><?php the_excerpt( ); ?></div>
	</a>
</div>
<?php endwhile; ?>
<div class="page-navigation">
    <div class="older"><?php previous_posts_link( '&laquo; 前へ' ); ?></div>
    <div class="newer"><?php next_posts_link( '次へ &raquo;' ); ?></div>
</div>
<?php $wp_reset_postdata(); ?>

 

③ カテゴリのリンクを作成する

ここから本題です。②の前にカテゴリのリンクを作成します。

<?php 
	$this_url = get_permalink( $post->ID );
	$tax1 = 'color'; //TAX1に自由なタクソノミ名を設定
	$tax2 = 'form'; //TAX2に自由なタクソノミ名を設定
	if ( isset( $_GET[$tax1] ) ) $tax1_get = $_GET[$tax1]; else $tax1_get = 'all'; //URLパラメータを取得
	if ( isset( $_GET[$tax2] ) ) $tax2_get = $_GET[$tax2]; else $tax2_get = 'all'; //URLパラメータを取得
	$tax1_terms = get_terms( $tax1, '&hide_empty=true' );
	if ( $tax1_terms ){ 
		$current = '';
		if ( $tax1_get == 'all' ) $current = 'current';
		$tax1_term_items = "t" .'<li><a href="'.$this_url.'?'.$tax1.'=all&'.$tax2.'='.$tax2_get.'" title="View all '.$tax1.'" class="'.$current.'">All '.$tax1.'</a></li>'. "n";
		foreach( $tax1_terms as $tax1_term ){
			$current = '';
			if ( $tax1_get == $tax1_term->slug ) $current = 'current';
			$tax1_term_items .= "t" .'<li><a href="'.$this_url.'?'.$tax1.'='.$tax1_term->slug.'&'.$tax2.'='.$tax2_get.'" title="'.$tax1_term->name.'" class="'.$current.'">' .esc_html( $tax1_term->name ). '</a></li>'. "n";
		}
	}
	$tax1_term_items = '<ul id="tax1">' ."n". $tax1_term_items. '</ul>' ."n";
	echo $tax1_term_items;

	$tax2_terms = get_terms( $tax2, '&hide_empty=true' );
	if ( $tax2_terms ){ 
		$current = '';
		if ( $tax2_get == 'all' ) $current = 'current';
		$tax2_term_items = "t" .'<li><a href="'.$this_url.'?'.$tax1.'='.$tax1_get.'&'.$tax2.'=all" title="View all '.$tax2.'" class="'.$current.'">All '.$tax2.'</a></li>'. "n";
		foreach( $tax2_terms as $tax2_term ){
			$current = '';
			if ( $tax2_get == $tax2_term->slug ) $current = 'current';
			$tax2_term_items .= "t" .'<li><a href="'.$this_url.'?'.$tax1.'='.$tax1_get.'&'.$tax2.'='.$tax2_term->slug.'" title="'.$tax2_term->name.'" class="'.$current.'">' .esc_html( $tax2_term->name ). '</a></li>'. "n";
		}
	}
	$tax2_term_items = '<ul id="tax2">' ."n". $tax2_term_items. '</ul>' ."n";
	echo $tax2_term_items;
?>

※特定のタクソノミに絞られている環境で、好みのデザインを適用するイメージで書いてますので、ループさせずに似たような処理を繰り返していますが、不特定多数のタクソノミで絞り込んでいくようなカタログサイトだったらadd_query_argなどの関数を使ってループさせた方が吉です。

出力したカテゴリはたぶんこんな感じ↓になるはず。

<ul id="tax1">
	<li><a href="http://example.com/items?color=all&form=all" title="View all color" class="current">color</a></li>
	<li><a href="http://example.com/items?color=red&form=all" title="レッド" class="">red</a></li>
	<li><a href="http://example.com/items?color=blue&form=all" title="ブルー" class="">blue</a></li>
	<li><a href="http://example.com/items?color=green&form=all" title="グリーン" class="">green</a></li>
</ul>
<ul id="tax2">
	<li><a href="http://example.com/items?color=all&form=all" title="View all form" class="current">form</a></li>
	<li><a href="http://example.com/items?color=all&form=square" title="square" class="">square</a></li>
	<li><a href="http://example.com/items?color=all&form=circle" title="circle" class="">circle</a></li>
	<li><a href="http://example.com/items?color=all&form=triangle" title="triangle" class="">triangle</a></li>
</ul>

$_GET[ $tax ]でパラメータを取得し、表示されているカテゴリのaタグのclassにcurrentを付与してます。上はパラメータが何も付いていないか、allが選択されている場合です。もし現在選択されているcurrentがblueとtriangleだとすると、以下のように代入されます。
#tax1↓
href=”~/items?color=all&form=triangle” class=””
href=”~/items?color=red&form=triangle” class=””
href=”~/items?color=blue&form=triangle” class=”current
href=”~/items?color=green&form=triangle” class=””

#tax2↓
href=”~/items?color=blue&form=all” class=””
href=”~/items?color=blue&form=square” class=””
href=”~/items?color=blue&form=circle” class=””
href=”~/items?color=blue&form=triangle” class=”current

④ tax_Queryにパラメータを代入してやる

最後にWP_Queryのtax_queryにカスタムタクソノミのパラメータを放り込んでやる必要があります。②の$argsを下記のように補完してやります。

<?php
	$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
	$args = array(
		'post_type' => 'item', //自由なポストタイプを設定
		'paged' => $paged,
	);
	if ( $tax1_get !== 'all' ) { 
		$tax1_arg = array(
			'taxonomy' => $tax1,
			'field' => 'slug',
			'terms' => $tax1_get,
		);
	} else {
		$tax1_arg = '';
	}
	if ( $tax2_get !== 'all' ) { 
		$tax2_arg = array(
			'taxonomy' => $tax2,
			'field' => 'slug',
			'terms' => $tax2_get,
		);
	} else {
		$tax2_arg = '';
	}
	if ( !empty($tax1_arg) || !empty($tax2_arg) ){
		$args['tax_query'] = array(
			$tax1_arg, $tax2_arg
		);
	}
?>

 


 

PHPの記述まとめ

phpの記述をまとめると次のようになります。適当にカスタマイズして下さい。post_typeをpostにタクソノミ名をcategoryとpost_tagにすれば、従来の投稿でも使えます。

<?php 
	//カテゴリのリンクを作成する
	$this_url = get_permalink( $post->ID );
	$tax1 = 'color'; //TAX1に自由なタクソノミ名を設定
	$tax2 = 'form'; //TAX2に自由なタクソノミ名を設定
	if ( isset( $_GET[$tax1] ) ) $tax1_get = $_GET[$tax1]; else $tax1_get = 'all'; //URLパラメータを取得
	if ( isset( $_GET[$tax2] ) ) $tax2_get = $_GET[$tax2]; else $tax2_get = 'all'; //URLパラメータを取得
	$tax1_terms = get_terms( $tax1, '&hide_empty=true' );
	if ( $tax1_terms ){ 
		$current = '';
		if ( $tax1_get == 'all' ) $current = 'current';
		$tax1_term_items = "t" .'<li><a href="'.$this_url.'?'.$tax1.'=all&'.$tax2.'='.$tax2_get.'" title="View all '.$tax1.'" class="'.$current.'">All '.$tax1.'</a></li>'. "n";
		foreach( $tax1_terms as $tax1_term ){
			$current = '';
			if ( $tax1_get == $tax1_term->slug ) $current = 'current';
			$tax1_term_items .= "t" .'<li><a href="'.$this_url.'?'.$tax1.'='.$tax1_term->slug.'&'.$tax2.'='.$tax2_get.'" title="'.$tax1_term->name.'" class="'.$current.'">' .esc_html( $tax1_term->name ). '</a></li>'. "n";
		}
	}
	$tax1_term_items = '<ul id="tax1">' ."n". $tax1_term_items. '</ul>' ."n";
	echo $tax1_term_items;
	$tax2_terms = get_terms( $tax2, '&hide_empty=true' );
	if ( $tax2_terms ){ 
		$current = '';
		if ( $tax2_get == 'all' ) $current = 'current';
		$tax2_term_items = "t" .'<li><a href="'.$this_url.'?'.$tax1.'='.$tax1_get.'&'.$tax2.'=all" title="View all '.$tax2.'" class="'.$current.'">All '.$tax2.'</a></li>'. "n";
		foreach( $tax2_terms as $tax2_term ){
			$current = '';
			if ( $tax2_get == $tax2_term->slug ) $current = 'current';
			$tax2_term_items .= "t" .'<li><a href="'.$this_url.'?'.$tax1.'='.$tax1_get.'&'.$tax2.'='.$tax2_term->slug.'" title="'.$tax2_term->name.'" class="'.$current.'">' .esc_html( $tax2_term->name ). '</a></li>'. "n";
		}
	}
	$tax2_term_items = '<ul id="tax2">' ."n". $tax2_term_items. '</ul>' ."n";
	echo $tax2_term_items;
	//tax_Queryにパラメータを代入
	$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
	$args = array(
		'post_type' => 'item', //自由なポストタイプを設定
		'paged' => $paged,
	);
	if ( $tax1_get !== 'all' ) { 
		$tax1_arg = array(
			'taxonomy' => $tax1,
			'field' => 'slug',
			'terms' => $tax1_get,
		);
	} else {
		$tax1_arg = '';
	}
	if ( $tax2_get !== 'all' ) { 
		$tax2_arg = array(
			'taxonomy' => $tax2,
			'field' => 'slug',
			'terms' => $tax2_get,
		);
	} else {
		$tax2_arg = '';
	}
	if ( !empty($tax1_arg) || !empty($tax2_arg) ){
		$args['tax_query'] = array(
			$tax1_arg, $tax2_arg
		);
	}
	//クエリを出力
	$wp_query = new WP_Query();
	$wp_query->query( $args );
	while ( $wp_query->have_posts() ) : $wp_query->the_post();
?>
<div class="post">
	<a href="<?php echo get_permalink( $post->ID );?>" title="<?php echo get_the_title( $post->ID );?">
		<h2><?php the_title( ); ?></h2>
		<div class="excerpt"><?php the_excerpt( ); ?></div>
	</a>
</div>
<?php endwhile; ?>
<div class="page-navigation">
    <div class="older"><?php previous_posts_link( '&laquo; 前へ' ); ?></div>
    <div class="newer"><?php next_posts_link( '次へ &raquo;' ); ?></div>
</div>
<?php wp_reset_postdata(); ?>

「wordpressのコメント欄をajax化する。」への21件の返信

  1. 参考にさせていただきました。

    尚、以下の行でエラーが出て動きませんでしたのでシングルクォートないしダブルクォートで囲いました。
    var matches = data.match(/([sS]*?)/);

    var matches = data.match(‘/([sS]*?)/’);

  2. 成功するときと失敗するときがあり、失敗するとURLの末尾に「#undefined」が付いて、commentsのdivがごっそり消え去ります。

    どうすれば。。。。

    1. ご報告ありがとうございます。

      undefinedを区別するように上記のjsを修正しました。

      commentsのdivが消えるのは、ポストはうまくいったにもかかわらずjsの処理が失敗しているせいです。
      undefinedの発生原因は、ajaxの読み出し先に誤ったhtmlタグなどがあるって失敗している可能性が高いのではないかと推測します。処理はphpなのでコメントがなくなるわけではないです。動作が改善しない場合は、テンプレートを見直すか、コメントIDを取得するタイプのajaxプラグインを使う必要があるかもしれません。
      undefinedが帰ってきた場合、ページをロードするようなjsの仕掛けをするのもいいかもしれませんね。承認待ちなどのシステムを活用していると、コメントが現れず不安を覚えて重ねて投稿、ということもあるかもしれませんので。そのうち考えます。

  3. 一番最初のコメント投稿だと、#commentsごと消えてしまいます。

    。。

  4. こんにちは!

    素晴らしいコードありがとうございます!
    一つ質問があるのですが、メッセージを表示させる場所を変更するには
    どうしたら良いのでしょうか?
    お手すきの間にでもご教示頂けると幸いです。

    1. var statusdiv = $('<div class="comment-ajax"></div>');

       
       this_form.prepend( statusdiv ).......

      上記の箇所で、div.comment-ajaxをフォームに対してprepend(先頭)に挿入しています。appendに変更してフォームの後方に入れるか、そもそもjsは触らなくて済むように、cssでポジションを指定するのが一番簡単な改変方法です。

    2. さっそくの返信ありがとうございます!

      appendにしてさらにCSSで調整することにしました。
      JSは全然わからなかったので助かりました〜m(_ _)m
      これを機に勉強してみようと思います。
      ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です