「カスタム投稿タイプを追加したら、一覧も個別ページも 404 になった」「パーマリンク構造を変えたら、一部の URL だけ表示されない」。WordPress の保守でよく出会う症状で、原因が rewrite rules(書き換えルール)が古いまま であることは少なくありません。
この記事では、rewrite rules が何で、どこに保存され、どんな場面で再生成(flush)が必要になるのかを整理します。WordPress 本体の一般的な仕組みの解説で、特定の製品に依存した話ではありません。
補足: Apache の
.htaccessと mod_rewrite の基本は、別記事の「.htaccess と mod_rewrite のルール」で扱っています。この記事は、その内側にある WordPress 自身のルール の話です。
2つの「書き換え」を分けて考える
WordPress の URL 処理には、役割の違う書き換えが2段あります。
| 段 | 担当 | 役割 |
|---|---|---|
| 1段目 | Web サーバー(.htaccess など) |
実在しないファイル・ディレクトリへのアクセスを index.php に渡す |
| 2段目 | WordPress 本体(rewrite rules) | index.php に届いた URL を、どの投稿・アーカイブかのクエリに変換する |
たとえば /news/2026/hello/ というアクセスは、1段目で index.php に渡され、2段目で「投稿タイプ news のスラッグ hello」といった内部クエリに解釈されます。1段目が正しくても、2段目のルールに該当がなければ WordPress は 404 を返します。 「flush が必要」と言われるのは、主にこの2段目の話です。
rewrite rules はどこにあるのか
2段目のルールは、wp_options テーブルの rewrite_rules というオプションに、正規表現と内部クエリの対応表として保存されています。リクエストのたびに全ルールを組み立て直すと負荷が大きいため、一度組み立てた結果をデータベースに置いておく設計です。
ここに落とし穴があります。ルールの元になる登録(投稿タイプ、タクソノミー、パーマリンク構造)を変えても、保存済みの rewrite_rules は自動では書き換わりません。 古い対応表のまま動き続け、新しい URL に対応する行がないので 404 になります。これを作り直す操作が flush です。
flush が必要になる主な場面
- パーマリンク構造を変えた(または変えようとした)とき
設定の「パーマリンク」画面で構造を保存すると、WordPress はルールを作り直します。 - カスタム投稿タイプやカスタムタクソノミーを追加・変更したとき
register_post_type()やregister_taxonomy()のrewrite引数(スラッグなど)を変えると、対応するルールが変わります。 - ルールを追加するプラグインを有効化・無効化したとき
独自の URL(エンドポイントなど)を持つプラグインは、有効化の時点でルールの再生成が必要です。 - サイトを別の環境へ移したとき
ドメインや設置ディレクトリが変わった場合、ルールの再確認が要ることがあります。 .htaccessが失われた・上書きされたとき
次の節で述べる「ハード」な再生成が関係します。
ソフトflushとハードflush
WordPress の関数 flush_rewrite_rules() は、引数 $hard で挙動が変わります。
- ソフト(
$hard = false): データベースのrewrite_rulesだけを作り直す。 - ハード(
$hard = true・既定値): 加えて、Apache 環境では.htaccessの WordPress 用ブロックも書き直す(書き込み権限があり、mod_rewrite が使える設定の場合)。
管理画面の「パーマリンク」画面で「変更を保存」を押す操作は、実質的にこの再生成にあたります。WP-CLI では次のように使い分けられます。
# 現在のルールを一覧で確認する
wp rewrite list --format=table
# データベース側だけを作り直す(ソフト)
wp rewrite flush
# .htaccess も書き直す(ハード)
wp rewrite flush --hard
# パーマリンク構造を設定する(保存時にルールも更新される)
wp rewrite structure '/%postname%/'
画面操作ができない状況や、複数サイトを順に確認したいときは、wp rewrite list で「期待する URL のルールが存在するか」を先に見ると、原因の切り分けに役立ちます。
よくある誤り: 毎回のリクエストで flush する
「404 が直るから」と、テーマの functions.php やプラグインの init フックに flush_rewrite_rules() を書いてしまう例があります。これは避けるべき書き方です。
- flush は、ルールを組み立ててデータベースへ書き込む処理を含む。アクセスのたびに走ると、不要な負荷になる。
- ハードの場合は
.htaccessへの書き込みも発生しうる。 - 動いているように見えても、問題の根本(登録のタイミング)が隠れてしまう。
正しい置き場所は、有効化フック(register_activation_hook)の中 です。そのとき、順序が重要になります。
function myplugin_register_types() {
register_post_type( 'news', array(
'public' => true,
'rewrite' => array( 'slug' => 'news' ),
) );
}
add_action( 'init', 'myplugin_register_types' );
function myplugin_activate() {
// 先に登録してから flush する。順序が逆だと新ルールが含まれない
myplugin_register_types();
flush_rewrite_rules();
}
register_activation_hook( __FILE__, 'myplugin_activate' );
function myplugin_deactivate() {
flush_rewrite_rules();
}
register_deactivation_hook( __FILE__, 'myplugin_deactivate' );
ポイントは、有効化の時点では init がまだ走っていない(このプラグインの登録が済んでいない)ため、flush の前に自分で登録関数を呼ぶ ことです。これを忘れると、flush しても新しいルールが含まれず、「有効化したのに 404」のままになります。
症状から原因を絞る順序
| 症状 | まず疑うこと |
|---|---|
| 新しい投稿タイプの個別ページだけ 404 | rewrite rules が古い。wp rewrite list で該当ルールを確認 |
| トップは表示されるが、投稿ページがすべて 404 | .htaccess の欠落、またはサーバー側で書き換えが無効 |
| ルールはあるのに 404 | スラッグの競合(同名の固定ページなど)、またはプラグインの登録順 |
| 管理画面の保存で直るが、翌日また 404 | 何かが定期的に .htaccess やルールを上書きしている |
最後の行は見落とされやすい点です。一時的に直って再発する場合は、flush を繰り返すより、何がルールや .htaccess を書き換えているのか を調べるほうが本筋です。
Nginx 環境での違い
Nginx は .htaccess を読みません。したがって「ハードflushで .htaccess を書き直す」という動きは意味を持たず、代わりにサーバー設定側に try_files などで index.php へ渡す記述が必要です。2段目(WordPress 本体のルール)は Apache でも Nginx でも同じ仕組みなので、1段目と2段目のどちらの問題かを切り分ける 考え方は共通です。
保守の場面での確認手順(例)
更新やメンテナンスの前後で、URL まわりを確認する手順の一例です。
- 作業前に、主要な URL(トップ、代表的な投稿、カスタム投稿タイプの一覧と個別ページ)を控えておく。
- 更新後、同じ URL を未ログインの状態で開き、表示を確認する。
- 404 があれば、まず
wp rewrite listで期待するルールの有無を見る。 - ルールが欠けていれば
wp rewrite flushを実行し、必要な場合のみ--hardを使う。 - 変更前のバックアップがあることを確認してから行う(考え方は3-2-1 ルールの記事を参照)。
flush 自体はデータの内容を変える操作ではありませんが、ハードの場合は .htaccess を書き換えるため、独自のルールを .htaccess に書き足している環境では事前に内容を控えておく と安心です。WordPress が管理するのは # BEGIN WordPress から # END WordPress の間だけで、その外側の記述は保持されます。
まとめ
- rewrite rules は WordPress 本体の URL 解釈の対応表で、
wp_optionsのrewrite_rulesに保存される。登録を変えても自動では更新されない - 404 の原因が「1段目(サーバー)」か「2段目(WordPress のルール)」かを切り分けると、対処が絞れる
- flush が要るのは、パーマリンク構造・投稿タイプ・タクソノミー・ルールを持つプラグインの変更時
flush_rewrite_rules()は毎回のリクエストで呼ばず、有効化フックの中で「登録してから」呼ぶ- 再発する 404 は、flush の繰り返しではなく、ルールや
.htaccessを書き換えている原因を探す