Wonderful! WordPress

カスタムフィールドの値で絞込み

この記事は公開または最後に更新されてから1153日が経過しています。情報が古くなっている可能性があるのでご注意下さい。

カスタムフィールドの値を使って、WP-Queryで絞込んで投稿を得るという事です。
ここの場合、鳥画像サイトなわけですが、新たにカモメだけのページを作ろうという事になって。
その時、過去に撮った個体かということを照合するのに、ある程度同じ特徴を持った個体に絞り込んでやった方が、手間が省けるという訳なのです。
具体的にいうとその特徴というのが、

  • 眼の色
  • 風切羽の黒い部分の枚数
  • 外側から三枚目の風切羽の模様の具合

とりあえずこの三つである程度分けられるかなということで、一つの投稿において一個体で、カスタムフィールドを使ってこれら三つの特徴を指定、保存してあります。
そしてそのカモメのページは固定ページにおいて表示します。詳細は以下のとおり。

  • カスタム投稿:gulls
  • カスタム分類:gull(カモメの種類)
  • カスタムフィールド:iris(眼の色)
  • カスタムフィールド:blackmark(風切羽の黒い部分の枚数)
  • カスタムフィールド:tongue(外側から三枚目の風切羽の模様の具合)

とりあえず絞りこむためのデータを送信するフォームなんぞを。
※注:下記form ではデータをpost で送信していますが、それではページネーションの際にデータが持ち回って引き継がれていきません。その問題は、get にて送信すれば機能します。このページの最後にその旨の追記があります。

<div id="formarea">
	<form action="https://strix.main.jp/?page_id=78381" name="narrowfrm" method="post">
		<p><span id="formhead">Narrow Search</span><br>

		<!--目の色-->
		<label for="iris">Color of Iris</label><br>
		<select name="iris">
			<option value="">all</option>
			<option value="w">light</option>
			<option value="m">medium</option>
			<option value="b">dark</option>
		</select><br>

		<!--風切羽の黒い部分の枚数-->
		<label for="blackmark">Number of<br> Primary Blacks</label><br>
		<input type="number" name="blackmark" id="blackmark" value="" min="4" max="9"><br>

		<!--外側から三枚目の風切羽の模様の具合-->
		<label for="tongue">P8 tongue</label><br>
		<select name="tongue">
			<option value="">all</option>
			<option value="n">no grey</option>
			<option value="t">no moon only grey</option>
			<option value="m">no mirror only moon</option>
			<option value="w">mirror and moon</option>
			<option value="r">no moon only mirror</option>
		</select><br>

		<!--カスタム分類”gull”の指定-->
		<label for="species">Gull sub-species</label><br>
		<select name="species">
			<option value="">all</option>
			<?php
				//カスタム分類”gull”の全ての要素を取得
				$args = array(
					'orderby'                  => 'name',
					'number'                   => '',
					'taxonomy'                 => 'gull',
				);
				$gulls = get_categories( $args );

				foreach( $gulls as $val ) {
					echo '<option value="' . $val->slug . '">' . $val->name . '</option>';
				}
			?>
		</select><br>
		<input type="submit" name="send" value="Search">
	</form>
</div>
PHP
CopyExpand

ここで絞り込むための情報は、前述のカスタムフィールドの値三つに加えてカスタム分類”gull”の値ということで合計四つになります。
この場合のWP-Queryに条件を指定するための引数の渡し方は次のようになります。尚、詳細はcodex 関数リファレンス/WP Queryをご覧あれ。

<?php
	$args = array(
		'post_type' => 'gulls',
		'posts_per_page' => 10,
		'paged' => $paged,
		'tax_query' => array(
			array(
				'taxonomy' => 'gull',
				'field'    => 'slug',
				'terms'    => 'vegae',
			),
		),
		'meta_query' => array(
			array(
				'key'     => 'iris',
				'value'   => 'b',
				'compare' => '=',
			),
			array(
				'key'     => 'blackmark',
				'value'   => 6,
				'compare' => '=',
			),
			array(
				'key'     => 'tongue',
				'value'   => 't',
				'compare' => '=',
			),
		),
	);
	$loop = new WP_Query( $args );
?>
PHP
CopyExpand

これをもとにして、あとはそれぞれの条件を変数にて組み立てれば良いという事になります。が、常に四つとも条件を指定するわけではなく、時によっては指定しない条件もあるわけで、それでは指定しない要素においてはどのように組み立てればよいのだろうかと。
実際にやってみると、指定したくない要素の配列をnull で渡しておけば、それにてちゃんと機能してくれました。

ということで、それでは呼び出されてこの値を受け取るこのページのテンプレートにての処理。

<?php
	$ssp = null;
	$iris = null;
	$blackmark = null;
	$tongue = null;

	$params = $_POST;
	if ( $params ) {
		foreach ( $params as $key=>$val ) {
			if ( 'species' === $key ) {
				$pattern = '/[^a-zA-Z]/';
				if ( ! preg_match( $pattern, $val ) ) {
					if ( $val and strlen( $val ) <25 ) {
						$ssp = array(
							'taxonomy' => 'gull',
							'field'    => 'slug',
							'terms'    => $val,
						);
					}
				}
			} elseif ( 'iris' === $key ) {
				if ( 'w' === $val or 'm' === $val or 'b' === $val ) {
					$iris = array(
						'key'     => 'iris',
						'value'   => $val,
						'compare' => '=',
					);
				}
			} elseif ( 'blackmark' === $key ) {
				$tmpval = intval( $val );
				if ( $tmpval > 3 and $tmpval < 10 ) {
					$blackmark = array(
						'key'     => 'blackmark',
						'value'   => $tmpval,
						'compare' => '=',
					);
				}
			}  elseif ( 'tongue' === $key ) {
				if ( 'n' === $val or 't' === $val or 'm' === $val or 'w' === $val or 'r' === $val ) {
					$tongue = array(
						'key'     => 'tongue',
						'value'   => $val,
						'compare' => '=',
					);
				}
			}
		}
	}
?>

<?php
	$args = array(
		'post_type' => 'gulls',
		'posts_per_page' => 10,
		'paged' => $paged,
		'tax_query' => array(
			$ssp,
		),
		'meta_query' => array(
			$iris,
			$blackmark,
			$tongue,
		),
	);
	$loop = new WP_Query( $args );
	$wp_query->max_num_pages = $loop->max_num_pages;
?>

<?php if ( $loop->have_posts() ):while ( $loop->have_posts() ) : $loop->the_post(); ?>
	//投稿があった時のループ処理
<?php
		endwhile;
	else : // ここから記事が見つからなかった場合の処理
?>
	<article class="post">
		<p>Sorry no post matched !!</p>
		<p>Please try again with another conditions.</p>
	</article>
<?php endif; ?>
PHP
CopyExpand

で、66行めのmax_num_pagesについて。
WP-Queryにて投稿セットを取得した場合、自作のページネーションリストが表示されなくなりました。
これは、$wp_query->max_num_pagesに総ページ数の値が入っていないのが原因とのこと。故に、その値を与えてやりさえすればなんてことなく機能されるようになります。逆に言えば、ページネーション機能が不必要ならば、最後の行はいらないということになります。
実を言うと、これまで固定ページにおいてカスタム投稿の投稿セットを取得するのにquery_postsを使っていました。query_postsであれば、ページネーションリストもなんの手間をかけることなく動作していましたし。

しかしながら、改めてcodex «テンプレートタグ/query posts»を読んでみると、「メインクエリーを変更するにはパフォーマンス面でも優れたより良いオプションが存在します。」とあり、「ひとことで言うと、query_posts() は決して使うべきではありません。」とまで書いてある。なんてこった!って感じです。パフォーマンス的に悪いということであれば、もはやこれを使用しているわけにはいかなくなります。

パフォーマンス的にはこのcodex に書いてあるアクションフック pre_get_postsを使うほうが良さげではあるのですが、残念ながらこのフックは固定ページでは有効ではありません。(codex にもちゃんと明記してありましたが、それを知らずに何度も試してみました。が、当然のこと、しらんぷりされました。)と、いうことでWP-Queryに落ち着くことになっています。
ちなみに実際のこのページはというとここです⇒Gulls wing-tip patterns → Search result page

2018/07/10 追記;
で、後で確認しようと思っていてそのまま放ったらかしになってしまったのですが、実は上記のページネーションの件、上記の状態ではちゃんと機能するわけはないのです。
ページ送りの際に肝心の絞り込むためのデータも持ち回って引き継いでいかないと、次のページにおいて投稿を絞り込むことができるわけがないのです。
その絞り込むためのパラメータは、url のクエリパラメータで持ち回ることになるのですが、これはなんのことはなくて、最初の段階でform から送信されるデータをpost ではなくget にて送信すれば良いだけのことです。まぁ、wordpress の検索機能もget にて送信するのが基本なので・・・。

と、いうことで、パラメータを送信するform を以下のようにget に変更しています。
自分の場合、送信先の検索結果表示ページは固定ページなので、その固定ページのアドレスもform のパラメータの一つとして送信しています。こうしないとurl に? が2つ付加されることになって、送信先の固定ページを指定できないためです。
get で送信することによって、url に絞り込みのためのパタメータが数珠つなぎになって付加されているので、ページネーションによってもそのパラメータが引き継がれていくことになります。

<div id="formarea">
	<form action="https://strix.main.jp/" name="narrowfrm" method="GET">
		<!--page_id=78381が固定ページのアドレス-->
		<input type="hidden" name="page_id" value="78381">
		<p><span id="formhead">Narrow Search</span><br>
		<!--目の色-->
		<label for="iris">Color of Iris</label><br>
		<select name="iris">
			<option value="">all</option>
			<option value="w">light</option>
			<option value="m">medium</option>
			<option value="b">dark</option>
		</select><br>

		<!--風切羽の黒い部分の枚数-->
		<label for="blackmark">Number of<br> Primary Blacks</label><br>
		<input type="number" name="blackmark" id="blackmark" value="" min="4" max="9"><br>

		<!--外側から三枚目の風切羽の模様の具合-->
		<label for="tongue">P8 tongue</label><br>
		<select name="tongue">
			<option value="">all</option>
			<option value="n">no grey</option>
			<option value="t">no moon only grey</option>
			<option value="m">no mirror only moon</option>
			<option value="w">mirror and moon</option>
			<option value="r">no moon only mirror</option>
		</select><br>

		<!--カスタム分類”gull”の指定-->
		<label for="species">Gull sub-species</label><br>
		<select name="species">
			<option value="">all</option>
			<?php
				//カスタム分類”gull”の全ての要素を取得
				$args = array(
					'orderby'                  => 'name',
					'number'                   => '',
					'taxonomy'                 => 'gull',
				);
				$gulls = get_categories( $args );

				foreach( $gulls as $val ) {
					echo '<option value="' . $val->slug . '">' . $val->name . '</option>';
				}
			?>
		</select><br>
		<input type="submit" name="send" value="Search">
	</form>
</div>
PHP
CopyExpand

カスタム投稿やらカスタムフィールドとは全く関係の無い事なのであるけれど・・・。
このページは、Google PAGESPEED INSIGHTS において、キャッシュ化していないにもかかわらず PC で 99 のスコアが出た。
理由はよくわからない。そんなにコンテンツの量が少ないわけではないし、code ブロックもまたしかり。まぁ、サーバーの状況だとかたまたまにしてもね。100ならなおのことではあるけれど。
google Pagespeed insights result

Leave a Reply!

JavaScript is necessary to send a comment.
You can edit and delete your comment if you input a edit key.
Edit key is necessary for attesting you when you edit and delete it.
The tag of HTML cannot be used in comment.
When you comment for the first time, it is displayed after the approval of the administrator.
Because I cannot speak English so much, it takes time to answer.
Required fields are marked *.

※Please enter more than 5 characters only alphabets.
※Edit or delete are possible for 2000 days after approval.

*

♠Simplistic Comment User Editable v4.0

♠When visitors leave comments on the site this site collect the data shown in the comments form, and also the visitor’s IP address and browser user agent string to help spam detection.
♠This site does not use cookie when visitors leave comments and commenter edit comment.
♠This site uses Akismet to reduce spam. Learn how your comment data is processed.

Comments feed

Trackback URL : https://strix.main.jp/wp-trackback.php?p=78881

Sanbanse Funabashi
2011.01.01 sunrise

Top

スクロールさせるか画像をクリックすると元に戻ります。