エラー処理を考察
前回の記事で、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は翻訳前提なので、まとめておいたほうが抜け漏れが無くなりそう。これは覚えておこう。