WordPressのパーマリンク設定で、%category%で作られる多階層時のスラッグを親カテゴリのみにする

Ads

つい先日悩んだので備忘録。WPのパーマリンク設定です。あまりスマートな方法ではありませんので、推奨しません。他に良い方法があったら教えてくださると嬉しいです。

と言う訳で助言を期待して記事にします。

パーマリンク設定で/%category%/を使うと記事のパーマリンクの文字列内に子カテゴリ、孫カテゴリも含まれます。これを、親カテゴリのみにする、という方法。

コード

パーマリンクはカスタム構造で

/%category%/%year%%monthnum%/%postname%.html

と設定しています。

なので、それに合わせたコードになります。

//post_linkフィルタをフック
add_filter( 'post_link', 'remove_children_category_slug', 10, 3 );
function remove_children_category_slug( $permalink, $post, $leavename ){
    //カテゴリのIDを取得
    $cats = get_the_category( $post->ID );
    if ( $cats ) {
        //ID順にソート
        usort( $cats, '_usort_terms_by_ID' ); 
        foreach( $cats as $cat ) {
          //親が存在するかチェック
          if ( $cat->parent ) {
              //文字列を分割して配列化
              $parentcategory = explode(" ",get_category_parents( $cat, false, ' ', true ));
              //配列から最上位のカテゴリ(親カテゴリ)を抽出
              $topcat = $parentcategory[0];
              $time = get_the_time('Ym');
          } else {
              //親がない場合はそのままスラッグを取得
              $topcat = $cat->slug;
          }
        }
    }
    //管理画面で設定したパーマリク構造にあわせる
    $permalink = home_url()."/".$topcat."/".$time."/".$post->post_name. ".html";
    //ドメイン/親カテゴリ/更新年月/記事名.htmlとしてreturnすれば子、孫カテゴリが外れた状態のパーマリンクになる
    return $permalink;
}

構造とマッチしないと404が返されます。

背景

背景的なもの。

色々と条件が重なって、どうしても取る必要が出てきました。条件としては

  • 記事ページは/parent/children/grandchild/postname.htmlではなく/parent/postname.htmlとしたい。
  • でもカテゴリアーカイブページは/parent/children/grandchildにしたい。
  • 親カテゴリ、子カテゴリは必ず選択されている(チェックが入ってる)必要がある
  • 「カテゴリベース」は利用できない。(カスタム投稿に影響が出る、パンくず等や他の諸問題の関係)
  • ページ数は数千ページあるので「プラグインを使って記事ごとに手作業で設定」等はできない
  • カテゴリの数は300以上ある

リニューアルで前のCMSは別だけどパーマリンクは維持したい、というよくある話です。

htaccessを使う以外で思いついた方法として、普通にパーマリンク設定をして個別記事のパーマリンクから子カテゴリ以下を取るに至りました。

実装したものの、あまり良い方法では無いような気がしてならないので、もっと良い方法があるなら無能な自分に是非ご教授頂きたく思います。