misoniction.com

カスタム投稿タイプのパーマリンクを変更する

試した環境

  • WordPress: 5.6.1
  • PHP: 7.3.5
  • MySQL: 5.7.28

実現したかっと事と、実際に起きたこと

newsというカスタム投稿タイプを作成し、news_categoryというタクソノミーを作成した。 そしてnews_taxonomyeventinfoというタームを作成した。
実現したかった事は下記の3つ。

  • /news/にアクセスした時は、カスタム投稿タイプnewsの記事一覧を表示
  • /news/event/にアクセスした時は、カスタム投稿タイプnewsかつタームがeventの記事を表示
  • /news/info/にアクセスした時は、カスタム投稿タイプnewsかつタームがeventの記事を表示

/news/にアクセスした時は、期待通りの表示になったのだが/news/event/news/infoにアクセスした時は、404になってしまった。 その時のパーマリンク設定は下記の通り

  • カスタム設定: /%category%/%postname%/
  • カテゴリベース: .
  • タグベース: .

解決方法

結論から言うと、リライトルールを追加して対応した。
Rewrite API/add rewrite rule
/news/eventにアクセスされたときにはpost_type=news&news_category=event, /news/infoにアクセスされたときにはpost_type=news&news_category=infoにリライトされるようにすればいいので、 functions.phpに記述する

// functions.php
/**
 * 投稿タイプのパーマリンクがpost_titleのままで良い時は、$linkを返すだけでも良い
 */
function generate_custom_post_link( $link, $post ): string
{
    if ( $post->post_type === 'news' )
    {
        return home_url( '/news/' . $post->post_title );
    } else {
      return link;
    }
}

function add_rewrite_rules( $rules ): array
{
    $terms = get_terms( 'news_category' );
    $new_rule = [];
  
    foreach ( $term as $term ) {
        $new_rule['news/('. $term->slug .')/?$'] = 'post_type=news$news_category=$matches[1]';
    }
    
    return $new_rule + $rules;
}

add_filter( 'post_type_link', 'generate_custom_post_link', 1, 2 );
add_filter( 'rewrite_rules_array', 'add_rewrite_rules');

タームがeventinfoで固定ならば、ハードコーディングでも良いが、ここは増えたり、減ったりする部分なので、 タームの数を取得してforeachで回してタームの数だけルールを追加する。
が、この記述だけではページネーションがある時に対応できないので、ルールを追記する

// functions.php
/**
 * 投稿タイプのパーマリンクがpost_titleのままで良い時は、$linkを返すだけでも良い
 */
function generate_custom_post_link( $link, $post ): string
{
    if ( $post->post_type === 'news' )
    {
        return home_url( '/news/' . $post->post_title );
    } else {
      return link;
    }
}

function add_rewrite_rules( $rules ): array
{
    $terms = get_terms( 'news_category' );
    $new_rule = [];
  
    foreach ( $term as $term ) {
        $new_rule['news/('. $term->slug .')/?$'] = 'post_type=news$news_category=$matches[1]';
        // 追記
        $new_rule['news/('. $term->slug .')/page/([0-9]+)/?$'] = 'post_type=news&news_category=$matches[1]&paged=$matches[2]';
    }
    
    return $new_rule + $rules;
}

add_filter( 'post_type_link', 'generate_custom_post_link', 1, 2 );
add_filter( 'rewrite_rules_array', 'add_rewrite_rules');

どういうクエリを投げればいいのかは、パーマリンクの設定からカスタム構造を選択して、値を空白にした後にアーカイブページに遷移するとURL欄にクエリが表示される。
もちろん、Debug BarDebug Bar Rewrite Rulesのようなプラグインを使っても良い。

この辺りが理解できると、URLを自由にゴニョゴニョできるようになると思う。

functions.phpを編集したあとは、パーマリンク設定を開かないと、設定が反映されないので、 書き換えたあとも何も変化が起きない時はパーマリンクを更新する。

あとプラグインが自由に使える環境にあるなら、custom Post Type Permalinksというプラグインを使えば簡単に自由に設定できる。

参考サイト