CODEMemorandum

【WordPress】カスタム投稿タイプの月別アーカイブまたは年別アーカイブが404になる場合の対応

カスタム投稿タイプの月別アーカイブまたは年別アーカイブをつくるとき、カスタム投稿タイプのパーマリンクを %post_id% に設定していると、wp_get_archives()で出力したアーカイブリストのリンク先が404エラーになってしまいます。
これはパーマリンクが %post_id% になっていると、日付アーカイブのURLと詳細ページのURLが競合してしまうため、パーマリンクが %post_id% の場合は日付アーカイブのURLに自動的に/date/が入る仕組みになっているためです。

以下、カスタム投稿名が「topics」の場合の例

【例】2022年の年別アーカイブのURL
https://example.ocm/topics/2022

【例】パーマリンクが %post_id% でIDが2022の投稿があった場合のURL
https://example.ocm/topics/2022

上記が競合してしまうのでパーマリンクが %post_id% の場合は日付アーカイブに自動的に/date/が入る

【例】パーマリンクが %post_id% の場合の2022年の月別アーカイブのURL
https://example.ocm/topics/date/2022

通常の「投稿」は、パーマリンクを %post_id% に設定すると、wp_get_archives()で出力されるURLに自動で/date/が入るのですが、「カスタム投稿タイプ」は自動で/date/が入らないので404エラーになってしまいます。(そのうち修正されるかもしれませんが、2022年12月時点ではエラーになります)

<?php $args = array (
  'type' => 'yearly',
  'echo' => 1,
  'post_type' => 'topics'
);
  wp_get_archives( $args );
?>
<li><a href='https://example.com/topics/2022/'>2022</a></li>

wp_get_archives() で出力するURLの文字列を置換する

wp_get_archives() で出力するURLに/date/を追加します。
‘echo’ => false で表示せず値として返して、str_replaceで /topics/ を /topics/date/ に置換しています。

<?php $args = array (
  'type' => 'yearly',
  'echo' => false,
  'post_type' => 'topics'
);
  $yearly_list = wp_get_archives($args);
  $yearly_list = str_replace('/topics/', '/topics/date/', $yearly_list);
  echo $yearly_list;
?>
<li><a href='https://example.com/topics/date/2022/'>2022</a></li>

これでカスタム投稿タイプの日付アーカイブのURLにも/date/が入りました!