WordPressカスタム投稿タイプが表示されない原因と解決方法【404エラー対処】

WordPress(ワードプレス)

WordPressでカスタム投稿タイプを追加したのに、公開したはずの記事にアクセスすると404エラーになる。管理画面には投稿がちゃんと並んでいるのに、URLを開くと「ページが見つかりません」と出てしまう。私も何度もこれに引っかかってきました。

コードも設定も間違っていないはずなのに表示されない、というのがこのトラブルのやっかいなところです。ただ、原因の多くは決まっていて、対処もそれほど難しくありません。この記事では、カスタム投稿タイプが404になる典型的な原因を挙げつつ、順番に解決していく方法をまとめます。

以前、通常の投稿ページが表示されなくなったときの話はこちらに書いています(WordPressで投稿ページが表示されないトラブルについて)。あわせて、カスタム投稿タイプの条件分岐タグまとめも参考にどうぞ。

カスタム投稿が404になる主な原因

カスタム投稿タイプの記事やアーカイブが404になる原因は、だいたい次の3つに絞られます。

1. リライトルールが更新されていない

一番多いのがこれです。WordPressは投稿や固定ページのURLを「リライトルール」という内部の対応表で管理しています。新しくカスタム投稿タイプを追加したり、URL構造を変えたりしても、このルールが古いままだとWordPressがページの場所を認識できず、404を返してしまいます。

次のようなタイミングで起こりやすいです。

  • カスタム投稿タイプを新しく追加した
  • register_post_type の rewrite や has_archive の設定を変更した
  • パーマリンク構造を変更した
  • テーマやプラグインを切り替えた

2. register_post_type の rewrite / has_archive の指定

register_post_type の rewrite は、その投稿タイプのURL書き換えを有効にするかどうかを決める引数です。既定は true で、投稿タイプ名がそのままスラッグに使われます。個別記事のURLがうまく効かないときは、ここで意図したスラッグになっているかを確認します。

アーカイブ(一覧ページ)を使いたい場合は has_archive を true にする必要があります。公式ドキュメントでも、has_archive は rewrite が有効なときに適切なリライトルールを生成すると説明されています。逆に言うと、これらを後から変更したのにリライトルールを更新していないと、変更が反映されず404のままになります。

3. テンプレートファイルが用意されていない

URLは通っているのに中身が真っ白、あるいは意図しない表示になる場合は、テンプレート階層の問題も疑います。WordPressはカスタム投稿タイプの表示に次の順でテンプレートを探します。

個別記事: single-{post_type}.php → single.php → singular.php → index.php

アーカイブ: archive-{post_type}.php → archive.php → index.php

専用の見た目にしたいなら single-{post_type}.php や archive-{post_type}.php をテーマに置きます。なくても上位のテンプレートにフォールバックするので、まずは表示自体が404になっていないかを切り分けるのがポイントです。

まず試す解決方法:パーマリンク設定を保存し直す

原因の大半を占めるリライトルールの問題は、管理画面からパーマリンク設定を保存し直すだけで解決することがほとんどです。設定内容を変える必要はなく、保存を実行すればリライトルールが再生成されます。

手順はこれだけです。

  1. WordPress管理画面にログインする
  2. 「設定」→「パーマリンク設定」を開く
  3. ページ下部の「変更を保存」をクリックする

何も変更していなくても、そのまま保存すればOKです。 管理画面からパーマリンクの変更を保存する 保存するとリライトルールが更新され、新しく追加したカスタム投稿タイプのURLが正しく認識されるようになります。公式ドキュメントでも、コードで明示的にルールを再生成していない場合の対処として、この「パーマリンク設定を保存し直す」方法が案内されています。カスタム投稿が404になったら、まずここから試すのがおすすめです。

flush_rewrite_rules() の正しい使いどころ

コードからリライトルールを更新する関数として flush_rewrite_rules() があります。これはリライトルールを再構築する関数で、確かに便利なのですが、使う場所を間違えると逆にトラブルの原因になります。

よく見かけるのが、init フックの register_post_type と一緒に毎回呼んでしまうパターンです。

function my_custom_post_type() {
    register_post_type('custom_post',
        array(
            'labels' => array(
                'name' => __('Custom Posts'),
            ),
            'public'      => true,
            'has_archive' => true,
        )
    );
}
add_action('init', 'my_custom_post_type');

投稿タイプの登録自体は上のように init で行いますが、ここに flush_rewrite_rules() を毎回書いてはいけません。公式ドキュメントは、これは重い処理なので必要なときだけ実行すべきで、ページ読み込みのたびに絶対に呼ぶな、とはっきり警告しています。

正しいのは、プラグインの有効化フックやテーマ切り替えのタイミングで一度だけ実行する形です。プラグインなら、投稿タイプを登録してからルールを再生成します。

function my_plugin_activate() {
    my_custom_post_type();   // 先に投稿タイプを登録
    flush_rewrite_rules();   // その後で一度だけ更新
}
register_activation_hook(__FILE__, 'my_plugin_activate');

テーマで扱う場合は after_switch_theme フックを使う方法もあります。ポイントは、投稿タイプの登録が終わったあとに実行することです。登録前に呼ぶと不完全なルールが作られてしまいます。

とはいえ、テーマの functions.php で手軽にやりたい、あるいは原因の切り分けを急ぎたいという場面では、コードをいじらずに管理画面からパーマリンク設定を保存し直すほうが安全で確実です。

カスタム投稿の404は、まずパーマリンク保存から

カスタム投稿タイプを追加したのに404になったら、切り分けの順番はこうです。

  1. 管理画面のパーマリンク設定を開き、そのまま保存し直す(多くはこれで解決)
  2. 直らなければ register_post_type の rewrite / has_archive の指定を確認する
  3. URLは通るのに表示がおかしいときは single-{post_type}.php / archive-{post_type}.php などテンプレートを確認する

flush_rewrite_rules() を使うなら init で毎回ではなく、有効化フックで一度だけ。この使い分けさえ押さえておけば、余計な負荷をかけずに済みます。原因の大半はリライトルールなので、まずはパーマリンク設定の保存から試してみてください。