カスタム投稿などを利用した際にパーマリンクを調整していると404NotFoundが出てしまうことがあります。そうしたときはリライトルールを追加することで解決できることもあります。具体的な例をあげて基本的なリライトルールの追加方法を解説してみます。
2019年7月18日
今回は下記のようなケースでリライトルールを追加して404NotFoundを回避してみたいと思います。まずは前提条件ですが、プラグインCustom Post Type UIで下記のような設定をしているとします。
カスタム投稿 => wordpress_customize
カスタムタクソノミー => lang
ターム => php、javascript、css
※カスタム投稿、カスタムタクソノミーはプラグインCustom Post Type UIで設定
各ページのURLについては下記のような設定とします。
ターム一覧画面(固定ページまたはアーカイブページ) => /wordpress_customize/
投稿一覧画面(各ターム毎) => /wordpress_customize/タームスラッグ/(/wordpress_customize/php/等)
投稿画面 => /wordpress_customize/投稿スラッグ/
本来、/lang/タームスラッグ/(/lang/php/等)となるところを、Custom Post Type UIのカスタムリライトスラッグにwordpress_customizeを設定してURLを上記のように変更した場合、投稿画面が404NotFoundになります。投稿一覧(各ターム毎)で、第2階層の文字列がタームスラッグになっています。これが正常に表示されているということはWordPressがwordpress_customizeの次の第2階層の文字列がタームスラッグであると認識しているわけで、投稿画面のURLが入力された際に第2階層の文字列である投稿スラッグを見て「そんなタームスラッグはないですよ」となって404NotFoundになるわけです。
/wordpress_customize/タームスラッグ/(/wordpress_customize/php/等) => 正常表示
/wordpress_customize/投稿スラッグ/ => 404NotFound
設定されているリライトルールは$wp_rewriteオブジェクトで確認できますので中身を見てみましょう。
<?php var_dump($wp_rewrite); ?>
object(WP_Rewrite)#2302 (25) {
・
・
["rules"]=>
array(227) {
・
・
["wordpress_customize/([^/]+)/?$"]=>
string(34) "index.php?lang=$matches[1]"
・
・
$wp_rewriteオブジェクトの中身を見てみるとruleというプロパティがあって、上記の場合で言うとその中に227個のキーと値の組み合わせが入っていることがわかります。8、9行目が投稿一覧画面(各ターム毎)のリライトルールを定義している部分で、wordpress_customize/の次に何かしらの文字列のあるURLの場合はindex.phpに対してlang=$matches[1]というパラメータを与えるということが書かれています。$matches[1]の部分は何かしらの文字列(キャプチャされた文字列)にあたります。例えばwordpress_customize/php/というURLの場合はindex.php?lang=phpという処理がおこなわれてphpの投稿一覧画面が表示されるわけです。ここで使用されるのはテンプレートtaxonomy-lang.phpです。
・エディタで学ぶ正規表現入門 (全18回) – プログラミングならドットインストール
投稿一覧画面(各ターム毎)のURLがデフォルトの/lang/タームスラッグ/(/lang/php/等)のままであればどちらも正常に表示されます。ただし、SEO対策の観点(カテゴリー強化)から投稿一覧画面(各ターム毎)もwordpress_customize以下のディレクトリに納めたいというケースもあるかと思います。今回はリライトルールを追加してどちらも正常に表示されるようにしたいと思います。
今回は考え方としては非常に簡単で、wordpress_customize/に続く第2階層にタームスラッグが来たら投稿一覧画面(各ターム毎)を表示。この場合はテンプレートtaxonomy-lang.phpが使われます。wordpress_customize/に続く第2階層に投稿スラッグが来たら投稿画面を表示。この場合はテンプレートsingle-wordpress_customize.phpが使われます。
ただし、今回は投稿一覧画面(各ターム毎)は既に正常に表示されているので、wordpress_customize/に続く第2階層に投稿スラッグが来た場合に投稿画面が表示されるようにすればよいでしょう。
/wordpress_customize/タームスラッグ/ => 既に正常に表示されているのでリライトルールを追加する必要はない
/wordpress_customize/投稿スラッグ/ => 投稿画面が表示されるようにリライトルールを追加
リライトルールの追加にはadd_rewrite_ruleを使えば簡単です。マニュアルにも書いてありますが基本形は以下のようになります。
・Rewrite API/add rewrite rule – WordPress Codex 日本語版
function add_new_rewrite_rule() {
add_rewrite_rule(
'wordpress_customize/投稿スラッグ/',
'index.php?post_type=wordpress_customize&name=投稿スラッグ',
'top');
}
add_action('init', 'add_new_rewrite_rule');
上記のようにルールを追加すれば、wordpress_customize/に続く第2階層に投稿スラッグが来た場合はindex.phpに対してpost_type=wordpress_customize&name=投稿スラッグというパラメータが渡りsingle-wordpress_customize.phpを読み込んでくれます。それではwordpress_customize/投稿スラッグの部分を作っていきます。
今回は単純に投稿スラッグを全て並べていくことにします。正規表現なので最終的には以下のような形にしてあげればOKです。
function add_new_rewrite_rule() {
add_rewrite_rule(
'wordpress_customize/((投稿スラッグ1|投稿スラッグ2|投稿スラッグ3|・・・))/?$',
'index.php?post_type=wordpress_customize&name=$matches[1]',
'top');
}
add_action('init', 'add_new_rewrite_rule');
それでは投稿スラッグ1|投稿スラッグ2|投稿スラッグ3|・・・を作っていきます。ループを回して各投稿のスラッグを取り出しつつ文字列を連結します。
$args = array('post_type' => 'wordpress_customize', 'posts_per_page' => -1, 'post_status' => 'publish');
$query = new WP_Query($args);
$count = $query->found_posts;
$str = '';
if ($query->have_posts()) : $i = 1; while ($query->have_posts()) : $query->the_post();
$str .= get_post_field('post_name', get_the_ID());
if ( $i < $count) {
$str .= '|';
$i++;
}
endwhile; wp_reset_postdata(); endif;
文字列を連結しているのは6、8行目で、投稿スラッグが取り出されるたびに$strの末尾に連結し、さらに|(縦棒)を連結しています。この|(縦棒:正規表現で「or」の意味)は最後は必要ないので、3行目で投稿の総数を出しておいてif文を使うことで最後に|(縦棒)が付かないようにしています。これで$strの内容が投稿スラッグ1|投稿スラッグ2|投稿スラッグ3|・・・となりましたので最終的には以下のような記述で完成です。リライトルールを変更した場合は管理画面の「パーマリンク設定」画面を開いてください(保存ボタンを押す必要はありません)。これでリライトルールが再構築されます。
■functions.php
add_action('init', 'add_new_rewrite_rule');
function add_new_rewrite_rule() {
$args = array('post_type' => 'wordpress_customize', 'posts_per_page' => -1, 'post_status' => 'publish');
$query = new WP_Query($args);
$count = $query->found_posts;
$str = '';
if ($query->have_posts()) : $i = 1; while ($query->have_posts()) : $query->the_post();
$str .= get_post_field('post_name', get_the_ID());
if ( $i < $count) {
$str .= '|';
$i++;
}
endwhile; wp_reset_postdata(); endif;
add_rewrite_rule(
'wordpress_customize/(('.$str.'))/?$',
'index.php?post_type=wordpress_customize&name=$matches[1]',
'top'
);
}
以上で「リライトルールを追加して読み込むテンプレートを切り替える」の解説を終わります。