【WordPress】カスタム投稿タイプのパーマリンクをカスタムするとアーカイブと個別記事が404になる(function.php)

WordPressのカスタム投稿タイプを作成して、URLを以下のようにしたかったので、post_type_linkrewrite_rules_arrayを使ってURLをカスタマイズしました。

▼アーカイブをこんなURLにしたい
https://example.com/カスタム投稿名/ターム

▼個別記事をこんなURLにしたい
https://example.com/カスタム投稿名/ターム/投稿ID

URLカスタマイズの方法は検索すると沢山でてきますので、ここでは省略します。

無事パーマリンクは期待した通りに整形されたのですが、
個別記事のリンクをクリックすると404になってしまいました。

リライトをリセットする為に、
管理画面 > パーマリンク設定の「変更を保存」をクリックしてみましたが、
変わらず404のまま。

ちなみに、TOPページ(index.php)が表示される、他のページが表示される場合はリライトは成功しているので、テンプレートの優先順位を調べたらよいと思います。

原因:リライトさせる正規表現と基本URLが間違っていた

rewrite_rules_arrayを設定する時に、正規表現とリダイレクトさせる基本URL(パラメーター付きのURL)が間違っていた事が原因でした。

以下が404を解決できたソースです。

add_filter( 'post_type_link', 'my_type_link', 1, 2 );
function my_type_link( $link, $post ){
    if ( 'my_post' === $post->post_type ) {

        // カスタム投稿名/ターム/にする
        $term = wp_get_post_terms( $post->ID, 'my_category' );
        if(!empty($term)){

            //タームが指定されている場合
            return home_url( '/my_post/' .$term[0]->slug. '/' .$post->ID );
        }else{

            //タームが指定されていない場合(お好みで)
            return home_url( '/my_post/other/' .$post->ID );
        }
    } else {
        return $link;
    }
}

add_filter( 'rewrite_rules_array', 'my_rewrite_rules_array' );
function my_rewrite_rules_array( $rules ) {
	$new_rules = array(
        
        //アーカイブページ送り
        'my_post(?:/([0-9]+))?/?$' => 'index.php?post_type=my_post&paged=$matches[1]',

        //個別記事
        'my_post/(.+?)/([0-9]+)$' => 'index.php?post_type=my_post&p=$matches[2]',

        //アーカイブ
        'my_post/([^/]+)(?:/([0-9]+))?/?$' => 'index.php?my_category=$matches[1]&paged=$matches[2]',
	);
	return $new_rules + $rules;
}

まず、post_type_linkでパーマリンクをターム入りに変更しました。

次に、問題の404の原因になっていたrewrite_rules_arrayですが、
以下の様に配列に指定しました。

リライトの指定の基本は配列に、
[整形したURLがマッチする正規表現]=>リダイレクト先の基本URL
のように書いてあげます。

■個別記事

規表現:my_post/(.+?)/([0-9]+)$

リライト先URL(基本URL):index.php?post_type=my_post&p=$matches[2]

■アーカイブ(カスタム投稿タイプの一覧)

正規表現:my_post/([^/]+)(?:/([0-9]+))?/?$

リライト先URL(基本URL):index.php?my_category=$matches[1]&paged=$matches[2]

■アーカイブページ送り

2019/07/03追記

あれ、カスタム投稿タイプの一覧のページ送りが404になる。という事で、以下を追加しました。

正規表現:my_post(?:/([0-9]+))?/?$

リライト先URL(基本URL):index.php?post_type=services&paged=$matches[1]

本当であれば、ページ送りは、

/my_post/page/2/

としたかったのですが、これだと個別ページと判断されてしまうので、パラメーターでページをつける事にしました。

実は今回、パラメーターを「paged」にしたところ、個別ページと判断されてしまい、「sample-page__trashed」という投稿記事が表示されてしまったので、

パラメーターを「page」に変更して対応しました。

他の方の役に立つかわかりませんが、function.phpでページ送りを作成した例も乗せておきます。

function wp_pagination($paged) {
	global $wp_query;
    
    //今のリンクを取得
	$link = esc_url( get_pagenum_link() );
   
    //ページ送りのベースのURLを作る
	if(preg_match('/page=/', $link)){

         //パラメータpageが付いているときは、page={ページ数}のページ数を%#%に置換
		$base = preg_replace('/page='.$paged.'/','page=%#%', esc_url(get_pagenum_link()));
	}else{
    
        //パラメータがついていないときは?page=%#%をつける
		$base = esc_url(get_pagenum_link()).'?page=%#%';
	}

    //ページ送り作成
	$page_format = paginate_links( array(
		'base' =>$base,
		'format' => '?page=%#%',
		'current' =>$paged,
		'total' => $wp_query->max_num_pages,
		'type'  => 'array'
	) );

    //この辺はお好みで
	if( is_array($page_format) ) {
		echo '<div><ul class="pagenation">';
		foreach ( $page_format as $page ) {
    		echo '<li class="pagenation__item">'.$page.'</li>';
		}
			echo '</ul></div>';
	}
	wp_reset_query();
}

リライトを確認できるプラグインRewrite Rules Inspectorが便利

今回色々調べていて、WordPressのリライトルールを確認できるプラグインがある事を知りました。とても便利だったのでおすすめです。

プラグイン名:Rewrite Rules Inspector

更新されていないようでしたが、WordPress 5.2.1で動作しました。

このプラグインを使って、整形したURLがどのルール(正規表現)にひっかかっているか、期待した通りになっているか、競合していないかなど調べる事ができます。

カスタム投稿タイプのアーカイブや個別記事が404になった時のおさらい

  1. 管理画面 > パーマリンク設定 「変更を保存」をクリックする
  2. Rewrite Rules Inspectorを使って期待した正規表現にマッチしているかなど確認
  3. リライト先URLが正しいか確認($matchesのキーなども確認)