エラー処理を考察
前回の記事で、get_post_type_archive_link()関数の判定でエラー(false)が返ってきたら処理をしないということを学び、他の関数のエラー時の戻り値を色々眺めていました。すると、エラー時にfalseを返さずWP_Errorというクラスオブジェクトをそのままreturnしている関数を見かけたので調べてみました。
WP_Errorクラスを紐解く
なにはともあれ、まずはCodexでWP_Errorの仕様を確認。
WP_Error は、プラグインと WordPress 自身のエラー処理を簡単に行えるようにするクラス(PHP のクラス)です。
Codex日本語版クラスリファレンス/WP Errorの説明より引用
WP_Error のインスタンスは一つか複数のエラーを表すエラーコードとメッセージを保持します。 また、ある変数が WP_Error のインスタンスであるかをis_wp_error()関数を使って判定できます。
なるほど、任意のエラー情報を複数保持させたい時に使うのか。ちょうど今作っているフォームの入力チェックなんかで使えそう。ちょっと中身を確認。まずはWP_Errorクラスのコンストラクタが何をしているか見てみる。
public function __construct( $code = '', $message = '', $data = '' ) {
if ( empty($code) )
return;
$this->errors[$code][] = $message;
if ( ! empty($data) )
$this->error_data[$code] = $data;
}
プロパティの配列$errors
と$error_data
にエラーコードをキーにしてメッセージとデータを渡しているんだ。これ、エラーメッセージが1つならこれで良いけど、それだとあまり利点を感じない。メソッドの中にadd()
というのがある。これがコンストラクタと同じ処理しているな。
public function add($code, $message, $data = '') {
$this->errors[$code][] = $message;
if ( ! empty($data) )
$this->error_data[$code] = $data;
}
add()
メソッドはコンストラクタと違って$code
と$message
が必須なわけね。では、空のインスタンスを作ってエラーメッセージ分add()
メソッドで追加するほうが美しいと思われる。ということで実験。
$error = new WP_Error();
$error->add( "name", "姓が入力されていません。" );
$error->add( "name", "名が入力されていません。" );
$error->add( "address", "住所が入力されていません。" );
var_dump( $error );
var_dump()
で中身を確認してみると、以下の通り。
object(WP_Error)[5772]
public 'errors' =>
array (size=2)
'name' =>
array (size=2)
0 => string '姓が入力されていません。' (length=36)
1 => string '名が入力されていません。' (length=36)
'address' =>
array (size=1)
0 => string '住所が入力されていません。' (length=36)
public 'error_data' =>
array (size=0)
empty
$code
に「name」を渡すとコードがかぶることなく2次元配列に保存されていきます。これを取り出す時は、メソッドが準備してあるのでそれを使用。
Codex日本語版クラスリファレンス/WP Errorの説明より引用
- get_error_messages($code)
- すべてのエラーメッセージ、または指定したコードにマッチするエラーメッセージを取得します。パブリックにアクセス可能で、エラー文字列の配列を返します。指定したコードにマッチするメッセージが無ければ空の配列を返します。
- get_error_message($code)
- エラーメッセージを一つ取得します。指定したコードの最初のメッセージを返します。コードを指定しなければ、先頭のコードが使われます。エラー文字列を返します。
get_error_message()
でエラーメッセージを一つ取得できるんだけど、「0」番目(0 => string ‘姓が入力されていません。’ (length=36))しか取れない……。名のエラーメッセージを取るには、get_error_messages()
でエラー全部取って「1」番目を指定するしかないか。例えば、入力が空でないかのチェックするような内容で、ループで回せるようなら使えるか。うーん、通常は一つの$codeに対しては、一つのエラーメッセージという考え方のほうが良さそう。
$error = new WP_Error();
$error->add( "surname", "姓が入力されていません。" );
$error->add( "name", "名が入力されていません。" );
$error->add( "address", "住所が入力されていません。" );
if ( empty( $surname ) ) {
echo $error->get_error_message( "surname" );
}
if ( empty( $name ) ) {
echo $error->get_error_message( "name" );
}
if ( empty( $address ) ) {
echo $error->get_error_message( "address" );
}
まぁ、WP_Errorクラスの生成とエラー判定は別々のメソッドにしてあげればエラー処理に関するメッセージなんかを一元管理できそう。単純なエラー判定なら普通の条件文でも良いと思うんだけど、入力フォームのようにエラー判定がたくさんあるような場面であれば、こういうやり方のほうが美しい。それにWordPressは翻訳前提なので、まとめておいたほうが抜け漏れが無くなりそう。これは覚えておこう。