status_header():ページの HTTP のステータスコードを返す(WordPress)

WordPress

ページを表示するときに返す、HTTP のステータスコード(404・410・429 など)を決めます。中では PHP の header() を呼んでいて、「HTTP/1.1 410 Gone」のように、コードに合う説明の言葉を付けて送ります。ヘッダーは本文より先に送るものなので、template_redirect など、表示が始まる前のフックで呼びます。

書き方

status_header( int $code, string $description = '' ): void
  • $code:返すステータスコードです。
  • $description(省略できる):コードのあとに付く説明の言葉です。省略すると、WordPress が持っている決まった言葉(410 なら Gone)を使います。
  • 戻り値:ありません。

使い方の例

作業環境(WordPress 7.1.2)で試した結果を、コメントに書いています。ページを表示したときに返ったヘッダーを見て確認しています。

なくしたページで 410 を返す

もう戻さないページは、404 ではなく 410(Gone)を返すと、なくしたことがはっきり伝わります。set_404() も合わせて呼ぶと、本文にはテーマの 404 のテンプレートが使われます。

add_action( 'template_redirect', function () {
    if ( '/old-campaign/' === $_SERVER['REQUEST_URI'] ) {
        global $wp_query;
        $wp_query->set_404();  // 本文は 404 のテンプレートにする
        status_header( 410 );  // 410 Gone
        nocache_headers();     // キャッシュさせない
    }
} );

// /old-campaign/ を開いたときのヘッダー
// 410 Gone
// Expires: Wed, 11 Jan 1984 05:00:00 GMT
// Cache-Control: no-cache, must-revalidate, max-age=0, no-store, private
// 本文:404 のテンプレート

ないページでは、WordPress がもう 404 を送る準備をしていますが、template_redirect で status_header( 410 ) を呼ぶと 410 に替わりました(http_response_code() で見ると、呼ぶ前が 404、呼んだあとが 410)。

あるページを 404 にする

投稿やページはあるけれど、条件によって「ない」ことにしたいときは、set_404() だけでは足りません。set_404() は WordPress の中の「404 のページ」という扱いを替えるだけで、ステータスコードは替えないためです。下の条件は例で、試したときはトップページで確認しました。

add_action( 'template_redirect', function () {
    if ( is_page( 'members-only' ) && ! is_user_logged_in() ) {
        global $wp_query;
        $wp_query->set_404();
        status_header( 404 );
        nocache_headers();
    }
} );

// set_404() だけのとき:本文は 404 のテンプレート、ステータスコードは 200 のまま
// 3 つとも呼んだとき:404 Not Found・Expires と Cache-Control も付いた

混み合っているときに 429 と Retry-After を返す

呼びすぎの相手に「少し待ってから」と伝えるときは、429 と Retry-After を合わせて返します。受け取る側は wp_remote_retrieve_header() で秒数を読めます。説明の言葉を自分で決めたいときは、2 つ目の引数に渡します。

status_header( 429 );
header( 'Retry-After: 120' );
nocache_headers();
echo 'しばらくしてから、もう一度お試しください。';
exit;

// 返ったヘッダー:429 Too Many Requests・Retry-After: 120・Expires・Cache-Control

status_header( 503, 'Maintenance' ); // 503 Maintenance

気をつけること

  • set_404() だけでは 404 にならない:上の例のとおり、ステータスコードは 200 のままでした。検索エンジンには「あるページ」として伝わるので、status_header( 404 ) も呼びます。
  • キャッシュを止めるヘッダーは付かない:status_header() はステータスコードの行だけを送ります。トップページで status_header( 410 ) だけを呼ぶと、Expires・Cache-Control は付きませんでした。410 や 404 にするときは nocache_headers() も呼びます。ページのキャッシュのプラグインでの動きは試していません。
  • 画面に何か出したあとは効かない:出力のバッファを切った設定で、echo のあとに status_header( 410 ) を呼ぶと、headers_sent() が true になっていて、200 のままでした。バッファが効いている設定では、少し出したあとでも 410 になることがありますが、それに頼らず表示の前に呼びます。
  • WordPress が知らないコードは送らない:status_header( 299 ) のように説明の言葉がないコードを渡すと、何もせずに終わり、200 のままでした。
  • 別のページへ移すときは、status_header( 301 ) ではなく wp_safe_redirect() を使います。

関連する関数

  • nocache_headers():ブラウザーなどにキャッシュさせないヘッダーを送る
  • WP_Query::set_404():表示を 404 のページの扱いにする
  • add_action():template_redirect などのタイミングで処理を動かす
  • wp_safe_redirect():サイトの中の別のページへ移す
  • wp_remote_retrieve_response_code():取得した応答のステータスコードを読む

参考

逆引きリファレンスの一覧へ