2015
2
03
WordPressの検索ページを人気順などで並び替えるボタンをつける

カテゴリとタグのアーカイブページに日付順や閲覧数順の並び替えボタンを実装してあったのですが、検索ページにも追加したので方法をまとめてみました。

この記事をスマホで読む

検索ページにも並び替えボタン

半年ほど前、このような記事を書いたのですが。

GET関数でどのボタンを押されたか判別してpre_get_posts()で並び替える(数はWP-PostViewsというプラグインを利用)、という。これが、アーカイブページなら

http://ateitexe.com/category/xxx/
 ↓
http://ateitexe.com/category/xxx/?sort=popular

このようにGET変数を付加して処理すればいけるな、という内容だったわけですが、検索ページだと

http://ateitexe.com/?s=キーワード

このようにもう既にGET変数がついているので、検索ページを並び替えたい場合は

http://ateitexe.com/?s=キーワード&sort=popular

という形にするためにもうちょっとテコ入れしないとうまくいかないなーということに気がついて、せっかくだからやってみようかな、と思ったわけです。

150203-1

このように、検索ページにも並び替えボタンがつきました。以下解説です。前記事からの派生という形で書いて行きますので、基本的な説明などは前記事と合わせて見ていってください。

先にpre_get_posts()のほうを

functions.php

function SortArchive( $query ) {
	if ( is_admin() || ! $query->is_main_query() )
		return;

	if ( $query->is_category() || $query->is_tag() || $query->is_search() ) {
		$sortset = (string)filter_input(INPUT_GET, 'sort');
		if ( $sortset != 'older' && $sortset != 'popular' && $sortset != 'unpopular' ) {
			$query->set( 'orderby', 'date' );
		} elseif ( $sortset == 'older' ) {
			$query->set( 'orderby', 'date' );
			$query->set( 'order', 'ASC' );
		} elseif ( $sortset == 'popular' ) {
			$query->set( 'meta_key', 'views' );
			$query->set( 'orderby', 'meta_value_num' );
		} elseif ( $sortset == 'unpopular' ) {
			$query->set( 'meta_key', 'views' );
			$query->set( 'orderby', 'meta_value_num' );
			$query->set( 'order', 'ASC' );
		}
		return;
	}
}
add_action( 'pre_get_posts', 'SortArchive' );

並び替える条件に、$query->is_search()も追加しただけ。ほぼ前回のと一緒です。

コードの変更点

概要

前の記事では

<?php if ( is_archive() ): //アーカイブページ ?>
	<?php if ( is_category() || is_tag() ): ?>
		//カテゴリ,タグアーカイブのとき
		//ここに並び替えボタンを実装
	<?php elseif( is_date() ): ?>
		//日付アーカイブのとき
	<?php endif; ?>
<?php endif; ?>

<?php if ( is_search() ): ?>
	//検索ページのとき
<?php endif; ?>

このような形で書いたのですが、1行目で「アーカイブページのときに」という条件で括っているために、検索ページは10~12行目に別で書いています。ここにも並び替えボタンを実装したいので、この形では非効率ですよね。なので、

<?php if( is_category() || is_tag() || is_search() ): ?>
	// カテゴリ,タグ,検索ページのとき
	//ここに並び替えボタンを実装
<?php endif; ?>

<?php if( is_date() ): ?>
	//日付アーカイブのとき
<?php endif; ?>

こういう形にしました。

詳細

<?php
if ( is_archive() || is_search() ) {
	global $wp_query;
	$total_results = $wp_query->found_posts; //件数を取得しておく
}
?>

<?php if( is_category() || is_tag() || is_search() ): // カテゴリ,タグ,検索 ?>
	<div class="result">
		<?php if( is_category() ): //カテゴリアーカイブのとき ?>
			カテゴリ "<?php single_cat_title(); ?>":<?php echo $total_results; ?>件<br />
		<?php elseif( is_tag() ): //タグアーカイブのとき ?>
			タグ "<?php single_tag_title(); ?>":<?php echo $total_results; ?>件<br />
		<?php elseif( is_search() ): //検索ページのとき ?>
			"<?php the_search_query(); ?>" で検索した結果:<?php echo $total_results; ?>件<br />
		<?php endif; ?>
		//並び替えボタンの実装
	</div>
<?php endif; ?>

<?php if( is_date() ): //日付アーカイブ ?>
	//前回と同じ
<?php endif; ?>

ベースの形に肉付けして、こんな感じ。更にハイライト部分に書くボタンの記述を以下に説明していきます。

CSSは同じですので前の記事を参照してください。

並び替えボタンの実装

htmlのイメージ

例えば前回カテゴリアーカイブでは、このようなhtmlが出力されるようにPHPを書きました。

<form method="get" action="http://ateitexe.com/category/xxx/">
	<input type="hidden" name="sort" value="newer" />
	<input type="submit" value="新しい順" />
</form>

これがもし検索ページだった場合、

<form method="get" action="http://ateitexe.com/">
	<input type="hidden" name="s" value="キーワード" />
	<input type="hidden" name="sort" value="newer" />
	<input type="submit" value="新しい順" />
</form>

検索されたキーワードの情報も一緒に持たせます。更にaction=の遷移先をトップページにすることで、ボタンを押された時に

http://ateitexe.com/?s=キーワード&sort=newer

というURLに遷移することができます。

この形を目指して、カテゴリ・タグアーカイブの場合はこっち、検索ページのときはこっち、という分岐をさせてhtmlを出し分けるように、PHPを書いていきます。

コード

前回のコード(アーカイブページのみ)

<?php
$url = explode('/', $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
$url_str ='http://'.$url[0].'/'.$url[1].'/'.$url[2].'/';
$sortset = (string)filter_input(INPUT_GET, 'sort');
$crt = ' class="sort_current"';
?>
<form method="get" action="<?php echo $url_str ?>">
	<input type="hidden" name="sort" value="newer" />
	<input type="submit"<?php if( $sortset == 'newer' ){ echo $crt; } ?> value="新しい順" />
</form>

「新しい順」に並び替えるボタンを例に、このように書いていました。

2,3行目で生成したURLを$url_strという変数に入れ、7行目の遷移先action=に指定してるので(詳細は前回の記事をご参照ください)、ここを分岐してやらなきゃいけないですね。

検索ページとアーカイブページで出し分け

<?php
if( is_search() ){
	$url_str = site_url('/');
} else {
	$url = explode('/', $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
	$url_str = 'http://'.$url[0].'/'.$url[1].'/'.$url[2].'/';
}
$sortset = (string)filter_input(INPUT_GET, 'sort');
$crt = ' class="sort_current"';
?>
<form method="get" action="<?php echo $url_str ?>">
<?php if( is_search() ): ?>
	<input type="hidden" name="s" value="<?php the_search_query(); ?>" />
<?php endif; ?>
	<input type="hidden" name="sort" value="newer" />
	<input type="submit"<?php if( $sortset == 'newer' ){ echo $crt; } ?> value="新しい順" />
</form>

検索ページの時はトップページURLを、それ以外(カテゴリ・タグアーカイブ)の場合は従来どおり生成したURLを、変数$url_strに入れます。これで遷移先が変化します。

後は12~14行目を追加で、検索ページのときだけ検索キーワードの情報を持たせます。検索文字列はthe_search_query()で表示することができます。

ただこの12~14行、これだけ見るぶんにはいいのですが、ボタンの数だけ同じことを書く羽目になるのでもうちょっと軽くしたいところ。

少コード化

<?php
if( is_search() ){
	$url_str = site_url('/');
	$srch = "\t" . '<input type="hidden" name="s" value="' . get_search_query() . '" />' . "\n";
} else {
	$url = explode('/', $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
	$url_str = 'http://'.$url[0].'/'.$url[1].'/'.$url[2].'/';
}
$sortset = (string)filter_input(INPUT_GET, 'sort');
$crt = ' class="sort_current"';
?>
<form method="get" action="<?php echo $url_str ?>">
<?php if( is_search() ){ echo $srch; } ?>
	<input type="hidden" name="sort" value="newer" />
	<input type="submit"<?php if( $sortset == 'newer' ){ echo $crt; } ?> value="新しい順" />
</form>

検索ページだった場合のみ、4行目で予め文字列を入れておいて13行目で出力する、という形へ。出力コードの見た目を整えるためタブや改行も含めています。

あと、さっきはthe_search_query()を使っていましたが、ここでは出力せずに取得するので、get_search_query()を使っています。

テンプレートタグの出力と取得の違いについてはこちら

エスケープ処理のご注意

こちらにあるとおり、get_search_query()$escapedというパラメータがあり、カッコ内にtrueでエスケープ処理を行い、falseでエスケープ処理を行いません。空だと、デフォルトでtrueとされます。

エスケープ処理とは特殊文字を無害化することですが、とても簡単に言うとこれを行わないと危険なのです。

どのバージョンからget_search_query()にエスケープ処理がデフォルトで実装されたのか特定できなかったのですが、WordPressの過去のバージョンではこの関数にエスケープ処理がなされていなかった、という経緯があるようです。(2008年くらいまで…?)

お使いのWPのバージョンにはくれぐれもお気をつけて、自己責任でお願いいたします。

最終コード

それでは、今までの流れでボタンを4つつけて、それぞれの区切りに「|」を入れてみると、

<?php
if( is_search() ){
	$url_str = site_url('/');
	$srch = "\t" . '<input type="hidden" name="s" value="' . get_search_query() . '" />' . "\n";
} else {
	$url = explode('/', $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
	$url_str = 'http://'.$url[0].'/'.$url[1].'/'.$url[2].'/';
}
$sortset = (string)filter_input(INPUT_GET, 'sort');
$crt = ' class="sort_current"';
?>
並び替え:
<form method="get" action="<?php echo $url_str ?>">
<?php if( is_search() ){ echo $srch; } ?>
	<input type="hidden" name="sort" value="newer" />
	<input type="submit"<?php if( $sortset != 'older' && $sortset != 'popular' && $sortset != 'unpopular' ){ echo $crt; } ?> value="新しい" />
</form>
|
<form method="get" action="<?php echo $url_str ?>">
<?php if( is_search() ){ echo $srch; } ?>
	<input type="hidden" name="sort" value="older" />
	<input type="submit"<?php if( $sortset == 'older' ){ echo $crt; } ?> value="古い" />
</form>
|
<form method="get" action="<?php echo $url_str ?>">
<?php if( is_search() ){ echo $srch; } ?>
	<input type="hidden" name="sort" value="popular" />
	<input type="submit"<?php if( $sortset == 'popular' ){ echo $crt; } ?> value="閲覧多" />
</form>
|
<form method="get" action="<?php echo $url_str ?>">
<?php if( is_search() ){ echo $srch; } ?>
	<input type="hidden" name="sort" value="unpopular" />
	<input type="submit"<?php if( $sortset == 'unpopular' ){ echo $crt; } ?> value="閲覧少" />
</form>

このような感じに。16行目は「日付が新しい順」をデフォルトとする、という意味で書いていますので、こちらも前回の記事をご参照ください。

以上です! どなたかのご参考になれたら幸いですー!

  • このエントリーをはてなブックマークに追加
  • follow us in feedly 518
  • RSSを登録

公開日:


コメントを残す




*印は必須項目です。コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にですがスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)


back to top