WordPress でステータスコード 404(Not Found)を返却するエラーページを作る
WordPress のサイトで、「指定された URL が存在しない場合、テーマ(テンプレート)で用意した 404 エラーページ(404.php
)の内容を返却します」というようなことが関連書籍等に記されていますが、サーバの設定によっては 404 エラーページを表示したにもかかわらず、HTTP レスポンスにステータスコード 200(OK)を付与してしまうケースがあります。
また、「指定された URL が存在しない場合」についてもバリエーションがあり、例えば、WordPress が解釈できるクエリー文字列が付与され、かつ存在しない URL であれば、適正なサーバの設定を行っても 404 エラーページが表示されない可能性が高いです。
このエントリーでは、指定された URL が存在しない場合、可能な限り 404 エラーページを返却させると同時に、スクリーンショットのように HTTP レスポンスのステータスコードに 404( Not Found)を返却する方法を紹介します。
この内容は 2.1.x から、先日リリースされた WordPress 2.2 まで確認しています。また内容について認識不足・認識誤り等ありましたらご指摘ください。適宜修正したいと思います。
1.ステータスコード 200 と 404 について
基礎知識として、HTTP レスポンスのステータスコード 200(OK)は「リクエストは成功」を意味しますので、404 エラーページを返却する場合は「リクエストURIと一致するリソースが見つけられなかった」ことを意味する 404(Not Found)を付与する必要があります。
ちなみに 404 は 4xx レスポンス(クライアントエラー)に含まれます。
2.ステータスコード 404 を返却する・対処その1(.htaccess の作成)
下記の内容を .htaccess の先頭に記述します。
ErrorDocument 404 /index.php?error=404
ドキュメントルート以外の場所に WordPress をインストールしている場合は、 "/" の前にドキュメントルートからのディレクトリを記述します。
下記のようにした場合は、エラーページの URL によって若干動作が異なります。
ErrorDocument 404 /404.php
「WordPress標準ガイドブック―導入&基本操作からフルチューンまで」では、クエリーによる設定(前者)が推奨されています。
WordPress標準ガイドブック―導入&基本操作からフルチューンまで マクラケン 直子 WordPress Japan 毎日コミュニケーションズ 2006-09 売り上げランキング : 14469 Amazonで詳しく見る by G-Tools |
3.ステータスコード 404 を返却する・対処その2(テーマ修正)
.htaccess をアップロードしてエラーの動作を確認したところ、存在しない URL を指定すると 404.php
がハンドリングされるようになりました。しかしながら、例えばデフォルト設定の個別ページやカテゴリーページの URL の末尾の数字に、存在しない ID を指定した場合は、そのテンプレートに記述したエラー処理の内容が表示されます。
例えば、個別記事の URL(デフォルト)は、末尾に "?p=記事番号" というクエリーが付与されますが、
http://user-domain/?p=10000
と、記事が存在しない URL を指定した場合は、404.php
が起動されるのではなく、正しいクエリー文字が URL に含まれていると判断してシングルポスト(single.php
)がハンドリングされます。
次に、起動されたシングルポストのテンプレートが下記の構造になっていると仮定します。
<?php get_header(); ?>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
:
(記事がある場合はここに記述されたテンプレートが展開)
:
<?php endwhile; else: ?>
:
(記事がない場合はここに記述されたテンプレートが展開)
:
<?php endif; ?>
<?php get_footer(); ?>
つまり、記事が存在しない ID が付与された正しいクエリーの URL で、上記の構造になっているテンプレートでは、「記事がない場合」の部分(赤色)が実際に処理されることになります。
ここには2つの問題があります。
- テンプレートを正常に処理しているので、ステータスコード 200(OK)を返却する
- 404 エラーであるにもかかわらず 404 エラー用テンプレートがハンドリングされない
この事象は、アーカイブ(archive.php
)やページ(page.php
)も同様です。アーカイブとして認識されるクエリーが URL に付与されると、アーカイブテンプレート内のエラー処理が起動します。
ステータスコード 404 を返却したいのはもちろんですが、できればエラーページについてはエラーとなる URL に関わらず、一意のページ、つまり 404.php
に処理を委ねた方が良い場合もあるのではないでしょうか(例えば 404 エラーページをカスタマイズしたい場合)。
この認識が間違っていないという前提で、下記にそれぞれの対処案を示します。
3.1 ステータスコード 404 を付与する
テーマファイルに含まれる、
- シングルポスト(
single.php
) - アーカイブ(
archive.php
) - ページ(
page.php
)
の先頭に、下記の青色の内容を追加します。
<?php if (!have_posts()) {
header("HTTP/1.1 404 Not Found"); } ?>
<?php get_header(); ?>
:
この設定は、処理すべき記事が存在しない場合、ステータスコード 404 を付与し、その後テンプレート後方に出現するエラー処理(前出リストの赤色部分)が実施されます。
3.2 404 エラー用テンプレートをハンドリングする
ここでは2つの方法を提示していますが、基本的に3.2.1を実施してください。
3.2.1 テンプレートを修正する(推奨)
3.1 項の修正内容と一部重複しますが、テーマファイルに含まれる
- シングルポスト(
single.php
) - アーカイブ(
archive.php
) - ページ(
page.php
)
の先頭に、下記の青色の内容を追加します。
<?php if (!have_posts()) {
header("HTTP/1.1 404 Not Found");
include (TEMPLATEPATH . '/404.php');
return; } ?>
<?php get_header(); ?>
:
この行を加えることで、処理すべき記事が存在しない場合は、テンプレートの通常処理を実行する前にレスポンスヘッダに 404 を付与し、404.php
に処理を移します。
3.2.2 ソースコードを修正する(非推奨)
今回のカスタマイズは、WordPress のソースコードを解析していて、先にこの方法に辿りつき、それからテンプレートに記述する案が思いつきました。
この方法を用いればテンプレートの修正をせずに、404.php
の内容を表示することができます。が、これは覚え書きレベルですので、実際には3.2.1項の修正を推奨します。
/wp-includes/classes.php
を任意のエディタで開き、下記の青色部分を追加します。
function handle_404() {
global $wp_query;
// Issue a 404 if a permalink request doesn't match any posts. Don't
// issue a 404 if one was already issued, if the request was a search,
// or if the request was a regular query string request rather than a
// permalink request.
if ( (0 == count($wp_query->posts)) && !is_404() && !is_search() && ( $this->did_permalink || (!empty($_SERVER['QUERY_STRING']) && (false === strpos($_SERVER['REQUEST_URI'], '?'))) ) ) {
$wp_query->set_404();
status_header( 404 );
nocache_headers();
} elseif( !have_posts() ) {
$wp_query->set_404();
status_header( 404 );
} elseif( is_404() != true ) {
status_header( 200 );
}
}
4.まとめ
WordPress でエラーとなる URL でリクエストされた場合に、正しいレスポンスを返却するためには、.htaccess の設定と、テンプレートの修正が必要です。どの部分の修正がどこに適用されるかについては下記の表を参考にしてください。
存在しない URL | あり得るクエリーの URL | ||
---|---|---|---|
.htaccess なし |
テンプレート修正 なし | サーバ依存 | 200 OK |
テンプレート修正 あり | サーバ依存 | 404 Not Found | |
.htaccess あり |
テンプレート修正 なし | 404 Not Found | 200 OK |
テンプレート修正 あり | 404 Not Found | 404 Not Found |
「サーバ依存」の部分は、自宅サーバとレンタルサーバで結果が異なったため、このような表記にしています。
5.その他
エラーページの表示に、常に 404.php
を利用するのであれば、各テンプレートの構造は(おおざっぱですが)、
<?php if (!have_posts()) {
header("HTTP/1.1 404 Not Found");
include (TEMPLATEPATH . '/404.php');
return; } ?>
<?php get_header(); ?>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
:
(記事がある場合はここに記述されたテンプレートが展開)
:
<?php endwhile; endif; ?>
<?php get_footer(); ?>
と、エラー処理を省略したフォーマットで統一できそうな気がします。
また上記までの修正で、ステータスコード 404 が付与されるようになりますが、レスポンスヘッダ全体を眺めた場合、X-PingBack ヘッダが付与されることついては懸念が残ってます。
- WordPressのタグアーカイブにnoindexを設定する方法
- WordPressで正しいユーザー・パスワードでログインできなくなった場合の対処
- WordPressのthe_excerpt()をカスタマイズする
- WordPressで抜粋の文字数を変更する方法
- WordPress 3.0にMovable Typeのタグをインポートする
- WordPress 3.0 で廃止された非推奨グローバル変数一覧
- WordPress の the_date を変更して記事ごとに日付を表示する
- 著作権表示の年号を自動更新するプラグイン V1.1 for WordPress
- 著作権表示の年号を自動更新するプラグイン for WordPress
- WordPress に Movable Type 風の「Syndicate this site」を表示する
- WordPress における日付/時間の表示とフォーマット変更方法
≫ 美しき404エラーページ集 from JJLW
404エラー、NotFoundは、HTTPステータスコードのひとつです。
さて、Notfound画面にもデザインあり!ということで、お洒落... [続きを読む]
≫ トリアエズで from prag -pranktone life archives-
急ぎ、404エラーページ作成。
いや、まったく忘れてた。
ってか、個別記事の URLって、末尾に "?p=記事番号" というクエリーがつくけど、
あ... [続きを読む]
≫ WordPressの404エラーをカスタマイズしてみたよ from Hinemosu
毎日10件ほど発生しているリクエストエラー(ページが見つかりません)を救うため、404エラーページをカスタマイズして... [続きを読む]