WordPressでSEOに理想的なディレクトリ構造とパンくずリストを作ってみる
連載:WordPressの理想的なURL構造を目指す

3.WordPressで/カスタムタイプ名/タクソノミー名_親ターム名/子ターム名/個別スラッグ/の形を実現してみる

目標のURL構造

「WordPressでSEO的に理想のパーマリンクを実現してみる」という事ですが、具体的なコードを書く前に、一つお伝えしたいことがあります。
前回の記事では理想のURLは

http://bookof.com/book/technical/pc/web/css/487311232X/
/カスタムタイプ名/親ターム名/子ターム名/孫ターム名/…/個別スラッグ/

としていましたが、本当は違います。
ってか無理…というか厳しい。

その理由は、今回理想のURL構造(ツリー型でディレクトリ構造のまま、URLをアドレスバーから直接操作しても内容のないページは作らない)を目指す為には、カテゴリーやタグ・タクソノミー名を含みたくない。
アーカイブページのタクソノミー名の部分を取りたい
とすると、cssというタグのアーカイブページも作りたくなると問題になってくる
アーカイブページのタクソノミー名の部分を取りたい
というように、リライトルールを適応しようとしても、タグなのかカテゴリーなのか、他のタクソノミーなのかを判断する材料がURLに含まれていないのでどっちを表示していいのか解らない。

ということで、今回目指すURLの中にどうしてもタクソノミー名が必要になってくる。
しかし、URLのツリー構造の中に内容のないページは含まれたくないので、今回の目標は下記のようにする!
GOGLEの推奨する綺麗なディレクトリ構造・URL構造
今回は上記のように、タクソノミー名とターム名をアンダースコアで区切る形にします。

使用テーマのfunction.phpに追記

では具体的なコードを書いてみましょう。
まずずっとご説明してきたとおり、WPに上記の新しいリライトルールを設定します。

使用しているテーマのfunction.php等に下記を追記

function ChangeRewriteRules($mypost, $myterm, $parents) {
	$newrules = array();
	if ( $myterm->parent == 0 ) {  //親タームがなかったら
		if (empty($parents)) {
			$newrules['archive'][$mypost . '/' . $myterm->taxonomy . '_(' . $myterm->slug . ')/?$'] = 'index.php?' . $myterm->taxonomy . '=$matches[1]';  //アーカイブページ用
			$newrules['archive'][$mypost . '/' . $myterm->taxonomy . '_(' . $myterm->slug . ')/page/([0-9]+)/?$'] = 'index.php?' . $myterm->taxonomy . '=$matches[1]&paged=$matches[2]';   //2ページ以降用
			$newrules['single'][$mypost . '/' . $myterm->taxonomy . '_' . $myterm->slug . '/([^/]+)/?$'] = 'index.php?' . $mypost . '=$matches[1]';
		} else {  //親があるターム用
			$newrules['single'][$mypost . '/' . $myterm->taxonomy . '_' . $myterm->slug . '/' . implode('/', $parents) . '/([^/]+)/?$'] = 'index.php?' . $mypost . '=$matches[1]';  //singleページ用
			$parents[count($parents)-1] = '(' . $parents[count($parents)-1] . ')/';
			$newrules['archive'][$mypost . '/' . $myterm->taxonomy . '_' . $myterm->slug . '/' . implode('/', $parents) . '?$'] = 'index.php?' . $myterm->taxonomy . '=$matches[1]';  //アーカイブページ用
			$newrules['archive'][$mypost . '/' . $myterm->taxonomy . '_' . $myterm->slug . '/' . implode('/', $parents) . 'page/([0-9]+)/?$'] = 'index.php?' . $myterm->taxonomy . '=$matches[1]&paged=$matches[2]';  //2ページ以降用
		}
	} else {  //親があったら
		$parentterm = get_term_by('id', $myterm->parent, $myterm->taxonomy);
		array_unshift($parents, $myterm->slug);
		$newrules = ChangeRewriteRules($mypost, $parentterm, $parents);
	}
	return $newrules;
}

function MyRewriteRules($rules) {  //引数:既に設定されているリライトルール
	$newrules = array();	$toriaezu = array();	$single = array();	$archive = array();
	$myposts = get_post_types(array('_builtin' => false));  //全カスタムタイプ取得②
	foreach($myposts as $mypost) {
		$mytaxonomies = get_taxonomies(array('object_type' => array($mypost))); //それのタクソノミー取得③
		foreach ($mytaxonomies as $mytaxonomie) {
			$myterms = get_terms( $mytaxonomie, array('hide_empty' => 0) ); //それのターム取得④
			foreach ($myterms as $myterm) {
				$toriaezu =  ChangeRewriteRules($mypost, $myterm, array()); //リライトルール配列を生成
				$single += $toriaezu['single'];  //順番調整⑤
				$archive += $toriaezu['archive'];
			}
		}
	}
	return $archive + $single + $rules;  //新しいルールを追加して返す⑥
}
add_filter('rewrite_rules_array','MyRewriteRules');

上記を簡単に説明すると、①のadd_filterで、rewrite_rules_arrayというフィルターフックに引っ掛ける。
rewrite_rules_arrayは引数に既に設定されているリライトールを
$rules[該当するルール] = “本当の姿”;
の形で持っているので、ここに新しいルールを追加して返します。

②で全てのカスタムタイプを取得してそれぞれをループ。
ループ内で、カスタムタイプ毎に設定されているタクソノミーを全て取得して、更にループ。
更にそれぞれのタクソノミーに設定されているタームを全て取得して、一つ一つに対して④の処理を実行。

④で
http://bookof.com/book/type_technical/pc/web/css/にアクセスがあったら、
index.php?type=cssの内容を表示しなさい。
http://bookof.com/book/type_technical/pc/web/css/page/2/にアクセスがあったら、
index.php?type=css&paged=2の内容を表示しなさい。
http://bookof.com/book/type_technical/pc/web/css/487311232X/にアクセスがあったら、
index.php?book=487311232Xの内容を表示しなさい。
の形の新しいルールを作成

配列に入っている順番で優先順位が変わるので⑤で調整して、
⑥で、古いルールに新しいルールを足して返す。

これで、新しいカスタムルールの設定は完了いたしました。

Custom Post Type Permalinksを入れる

次に「Custom Post Type Permalinks」プラグインを入れて、カスタム投稿タイプのパーマリンクの設置を変更いたします。
カスタム投稿を作ったら、それに割り当てるタクソノミーが色々あると思います。
今回の場合は
type (本のジャンル)
その他に例えば価格(price)・出版社(publisher)・著者(writer)等が考えられます。
その中から、singleページヘのURLのベースとなるタクソノミーを選びます。

http://bookof.com/book/price_1500-2000/
http://bookof.com/book/publisher_oreilly/
http://bookof.com/book/type_technical/pc/web/css/

今回の場合は、ユーザービリティ等を考えて

本の種類の軸
http://bookof.com/book/type_technical/pc/web/css/487311232X/

を本詳細ページまでのベースのURLとします。

その場合は、カスタム投稿タイプのパーマリンクの設置の
「book」のフィールドに
/type_%type%/%postname%/
と入力して変更を保存
(typeの部分は、詳細ページへの軸となるタクソノミー名に変更して下さい。)
カスタム投稿タイプのパーマリンクの設定

上記でとりあえず理想のURLにアクセスした際に、URLを解決してパラメーターから正しいページの内容を表示できるようになりました。

http://bookof.com/book/type_technical/pc/web/css/
http://bookof.com/book/type_technical/pc/web/css/page/2/
http://bookof.com/book/type_technical/pc/web/css/487311232X/
でアクセスできるようになった!

この形なら、アドレスバーを直接操作しても404ページは含まれずに、本の種類の軸で正しいツリー構造になっている。(pageの事は置いといて下さいっ汗)

これで理想のURLにアクセスして内容を表示できるようになりましたので、今度は「Breadcrumb NavXT」プラグインを使って、このURL構造にぴったしあったパンくずリストを作ってみよう。

著者