「wp_die カスタマイズ」でググっても日本語のページが該当しなかったので書いておきます。
WordPressにはいくつかのエラーページがあります。
- 404エラー
- これは該当するURLが存在しなかったときですね。テーマフォルダ内に404.phpを置いておけば大丈夫です。Codexにやり方が書いてあります。
- データベース接続エラー
- WordPressがデータベースに接続できなかったときに表示される画面です。表示されるタイミングとして一番多いのは、はてぶでホッテントリに入ったりYahooニュースに紹介されたりして大量のアクセスを食らったときでしょうか。今はどうか知りませんが、コリスさんとかIDEA*IDEAさんとかはたまになってましたね。これはdogmap.jp「WordPress のデータベースエラーページをカスタマイズ」にやり方が書いてあるので、そのとおりやればよろしいです。メンテナンスモード時の表示についてもドロップインというやり方で同じように変更できます。
- wp_die
- これが本題です。WordPressにはwp_dieという関数があります。WordPressが処理を行う上で、以上が発生した場合に呼び出される関数ですね。このカスタマイズ方法について説明します。
wp_dieのデフォルトの挙動
さて、wp_dieというのはPHPのdie関数と同じく、「もうこれ以上は処理しないよ」という緊急避難的な関数です。一応メッセージは表示されますが、いたってシンプル。関数の性質上、公開画面でも管理画面でも呼び出されるので、シンプルにしておいた方がいいという結論なんでしょうね。
この画面に遭遇するパターンは以下です。
- コメントフォームに何も入れないで送信しちゃった
- nonceが設定されていないログアウトのリンクを踏んだ
普通のブログとしてWordPressを使っている分にはお目にかかることも少ないのですが、Webアプリっぽくフォームをたくさん使っている場合はwp_dieが使えると便利です。使い方はこんな感じですね。
//なんらかの処理を行い、エラーがあった場合はwp_dieを実行 if($error){ wp_die("エラー: 不正な処理がありました", "Internal Server Error: 私のブログ"); } //これ以降は実行されない
wp_dieをカスタマイズする
wp_dieをカスタマイズするには、まず自作の関数を2つ用意します。一つ目はwp_dieで画面をレンダリングする関数名を指定する関数(my_wp_die_handlerとか)で、もう一つは実際にレンダリングをする関数(my_wp_die)ですね。まずは一つ目の関数を指定する関数を書いて、フィルターフックにひっかけます。テーマ内のfunctions.phpとかに書いておけばいいでしょう。
function my_wp_die_handler($function){ //get_bloginfoが使えれば使う。 //なければデフォルトのwp_dieを使う if(function_exists("get_bloginfo") && "" != get_bloginfo("template_directory")){ return "my_wp_die"; }else{ return $function; } } add_filter("wp_die_handler", "my_wp_die_handler", 1000);
一応、テーマディレクトリを参照できるかどうかを確認して、できなければ通常のものを使うようにしています。なぜこんな風にしているかというと、wp_dieはその性質上、どこで呼び出されるかわからないんですね。場合によってはWordPressがテーマを取得する前に実行されるかもしれません。それを防ぐために一応チェックしてます。まあfunctions.phpに書いてあるなら大丈夫だとは思いますが、念のため。
さて、あとはmy_wp_dieをfunctions.phpに書けばいいんですが、エラー処理などけっこう書くことが多いです。もともとwp_dieのレンダリングに使われていた関数_default_wp_die_handler(wp-includes/functions.phpに定義されてます)はこんな感じです。
長いですね。IE用におまじない(IEはエラーページの容量が小さいとブラウザが勝手に表示を変える)を書いているのが泣けます。これと同じのを書くのはめんどくさいですし、間違ってしまうかもれません。しかし、多くの人が変えたいのは見た目だけだと思いますので、まるまるコピペして、関数名をmy_wp_dieに変更した後、<html>〜</html>の中だけこんな感じで変えます。
<html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) && function_exists( 'is_rtl' ) ) language_attributes(); else echo "dir='$text_direction'"; ?>> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title><?php echo $title ?>::<?php bloginfo('name'); ?></title> <link rel="stylesheet" href="<?php bloginfo("stylesheet_url"); ?>" type="text/css" /> <link rel="shorcut icon" href="<?php bloginfo("template_directory"); ?>/images/favicon.ico" /> <?php endif; ?> </head> <body id="error-page"> <div class="head"> <h1> <a href="<?php bloginfo('site_url'); ?>"> <img src="<?php bloginfo("template_directory"); ?>/images/header-logo.png" alt="<?php bloginfo("name"); ?>" /> </a> </h1> <p class="description"><?php bloginfo('description'); ?></p> </div> <?php endif; ?> <div class="message"> <?php echo $message; ?> </div> </body> </html>
要はCSSのパスだけ自分のテーマのものに変えて、ロゴとかを出しただけですね。ちなみに19行目に謎のendif;がありますが、これは管理画面でヘッダーを出力したあとにwp_dieが呼び出されるケースがあるようなので、消さない方がいいです。もちろん、その場合、headセクションは出力されないので見た目をコントロールすることはできません。ともかく、これでwp_dieがカスタマイズできました。よかったですね。
おまけ1: 関数の定義元をどうやって見つけるか
WordPressや昨今はやりのオブジェクト指向フレームワークは膨大な量のコードがはじめっから書かれているので、どこでなにがどうなっているのか、細かくはわかりません。
そういう場合、関数の定義元を探る必要があります。僕はAptana Studioというのを使っているので、「なんだこの関数は?」と思ったら関数にフォーカスしてF3を押してます。そうすると、定義元に飛べるんですね。ある程度のIDEなら普通は備わっている機能です。他にもフォルダ単位で文字列を検索したりする機能もよく使います。しょぼいテキストエディタや古いDreamWeaverを使っている人はこれができなくて人生を損している可能性があるので、色々と考えなおしてみてください。ちょっと古いですが、参考リンクを挙げておきます。EC Studio 技術ブログ「テキストエディタからPHPEclipseへ移行した決め手」
おまけ2: エラーページのデザイン
WordPressに限った話ではないのですが、デザイナーさんで何も言わなくてもエラーページを作ってくれる人がいます。これは大変ありがたいのですが、3カラム構成のサイトでメインカラムにエラーメッセージを表示しただけのデザインのときがあります。
エラーにもいろいろあって、404とかは本気のエラーじゃないんでそれでもいいですが、500とかはわりと本気のエラーなので、いろんなコトできないんですね。サイトの他の部分で当たり前に出力されていたもの(グローバルナビとか)が出力できなかったりします。
なので、本気のエラーページをデザインするときは極力シンプル(基本はエラーメッセージだけで、できれば1カラム)で、あきらかにエラーとわかるデザインだと嬉しいですね。Twitterのくじら画面みたいな。
あと、エラーメッセージはプラグラム側でpタグにくるんで出力されることが多いので、「どう考えてもこれvertical-align:middleじゃないと駄目だろjk」みたいなデザインはイヤです。マークアップ上の工夫がいらないシンプルな奴が嬉しいですね。
まあ、500エラーとかまできちんと作りこんでいるサイトはあんまりないですし、IISのエラー画面とかApacheの403 Forbiddenとかはよく見るので別にいいっちゃいいんですが。というわけで、終わり。