【WordPress】カスタム投稿タイプのパーマリンクをカスタムするとアーカイブと個別記事が404になる(function.php)
WordPressのカスタム投稿タイプを作成して、URLを以下のようにしたかったので、post_type_link、rewrite_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になった時のおさらい
- 管理画面 > パーマリンク設定 「変更を保存」をクリックする
- Rewrite Rules Inspectorを使って期待した正規表現にマッチしているかなど確認
- リライト先URLが正しいか確認($matchesのキーなども確認)