WP_Error の扱い方|is_wp_error の判定とエラーの作り方・返し方

結論

WP_Error は、エラーコード、メッセージ、補足データを持つ、WordPress 共通のエラーオブジェクトです。関数が失敗したときに false や 0 の代わりに返され、受け取った側は is_wp_error() で必ず判定します。

押さえる点は4つです。

  1. if ( $result ) では判定できない。WP_Error オブジェクトは真と評価される
  2. 自作関数でも、失敗は WP_Error を返し、成功時と型を分ける
  3. 複数のエラーは add() で積み、has_errors() で確認してから返す
  4. REST API では、第3引数の data に status を入れると HTTP ステータスになる

原因・仕組み

WP_Error はクラスなので、返り値が成功した値か失敗かは型で区別します。公式リファレンスでも、返り値が WP_Error かどうかを調べるために is_wp_error() を使うと説明されています。

主なメソッドは次のとおりです。

メソッド 役割
add( $code, $message, $data ) エラーを追加する
get_error_code() 最初のエラーコードを返す
get_error_codes() すべてのエラーコードを配列で返す
get_error_message( $code ) メッセージを返す(コード省略で最初のもの)
get_error_messages() すべてのメッセージを配列で返す
get_error_data( $code ) 補足データを返す
has_errors() エラーが1件以上あるか
add_data( $data, $code ) 補足データを追加・置換する
merge_from( $other ) 別の WP_Error を取り込む

手順(サンプルコード)

バリデーション関数

function ks_validate( $data ) {
    $errors = new WP_Error();

    if ( empty( $data['name'] ) ) {
        $errors->add( 'missing_name', '名前は必須です。', array( 'field' => 'name' ) );
    }
    if ( ! isset( $data['age'] ) || ! is_numeric( $data['age'] ) ) {
        $errors->add( 'invalid_age', '年齢は数値で指定してください。', array( 'field' => 'age' ) );
    }

    if ( $errors->has_errors() ) {
        return $errors;
    }
    return array(
        'name' => sanitize_text_field( $data['name'] ),
        'age'  => (int) $data['age'],
    );
}

呼び出し側

$result = ks_validate( $_POST ); // 実際には nonce と権限の確認を先に行う
if ( is_wp_error( $result ) ) {
    foreach ( $result->get_error_messages() as $message ) {
        echo '<p class="error">' . esc_html( $message ) . '</p>';
    }
    return;
}
// 成功時は $result を使う

REST API で返す

return new WP_Error( 'ks_forbidden', '権限がありません。', array( 'status' => 403 ) );

動作確認(検証環境と結果)

WordPress 7.1.2(日本語)、PHP 8.2.12(testswp-error-handling-is-wp-error.md に全文)。

確認内容 結果
空の配列で ks_validate() is_wp_error() が true
if ( $r ) による判定 真になる(WP_Error は真と評価される)
get_error_codes() missing_name, invalid_age
get_error_code() missing_name(最初のもの)
get_error_message() 名前は必須です。
get_error_message(‘invalid_age’) 年齢は数値で指定してください。
get_error_data(‘invalid_age’) {“field”:”age”}
正しい入力 配列が返り、is_wp_error() は false
add_data() で2つ目のデータを追加 get_error_data() は後のデータ(’data A2’)を返した。get_all_error_data() では ‘data A1’ と ‘data A2’ の両方が取得できた
merge_from() コードが a, b に統合された
wp_insert_post( 空, true ) WP_Error(コード empty_content、メッセージ「本文、タイトル、抜粋が空欄です。」)
wp_remote_get(存在しないドメイン) WP_Error(コード http_request_failed)
get_term( 999999, ‘category’ ) NULL(WP_Error ではない)
get_term( 999999, 存在しないタクソノミー ) WP_Error(コード invalid_taxonomy)
REST: rest_convert_error_to_response() ステータス 403、data に code と message

get_term() のように、同じ関数でも「見つからない」は NULL、「引数が不正」は WP_Error と、返り値が分かれるものがあります。公式リファレンスで戻り値の型を確認してください。

WP_Error の扱い方の注意点

  • エラーメッセージを画面に出すときは、esc_html() などでエスケープします。メッセージにユーザー入力を含める場合は特に注意してください。
  • エラーコードは、プレフィックス付き(ks_ など)にして、他のプラグインと衝突しないようにします。
  • ユーザーに見せるメッセージと、ログ用の詳細情報(データ)を分けて持たせると、再利用しやすくなります。
  • add_data() で同じコードにデータを追加すると、get_error_data() が返すのは最新のデータだけです。WordPress 5.6 以降は、それ以前のデータも内部に残り、get_all_error_data() で取り出せます。複数の情報を確実に1回で渡したいときは、配列にまとめて渡すと扱いやすくなります。
  • 多言語化するメッセージは __() で包みます。

WP_Error の扱い方でよくあるミス

  • if ( ! $result ) で判定して、WP_Error をそのまま通してしまう。
  • wp_insert_post() に第2引数 true を渡さず、失敗が 0 で返ってきて原因が分からない。
  • wp_remote_get() の戻りに wp_remote_retrieve_body() をかけ、WP_Error のまま空文字になる。
  • WP_Error を echo してしまう(オブジェクトなのでエラーになる)。

WP_Error の扱い方のチェックリスト

  • 外部の関数を呼んだ戻り値を is_wp_error() で判定したか。
  • 自作関数の失敗は WP_Error で返しているか。
  • REST のエラーに status を付けたか。
  • メッセージを出力するとき、エスケープしているか。
  • ログに残す情報と、画面に出す情報を分けたか。

WP_Error の扱い方のFAQ(よくある質問)

Q. WP_Error を例外(try/catch)に置き換えられますか。
A. WordPress のコア関数は WP_Error を返す設計なので、混在させると呼び出し側が複雑になります。自作コードでは WP_Error に統一するのが無難です。

Q. メッセージの取り出しで空になります。
A. エラーコードを指定していて、そのコードが存在しない可能性があります。get_error_codes() で確認してください。

Q. is_wp_error() とクラスの instanceof の違いは。
A. 機能は同じで、is_wp_error() は WordPress の関数として用意されています。どちらでも構いませんが、プラグインの統一性のため is_wp_error() を使う例が多いです(is_wp_error() の使い方|説明・引数・注意点)。

筆者の見解(WP_Error の扱い方)

私見では、WP_Error を扱うコードの品質は、呼び出し側の判定漏れで決まると考えます。関数を呼んだら次の行で is_wp_error() を書く、という習慣をつけると、リリース後の原因不明の不具合が減ります。自作関数でも、false を返す設計より、理由を持てる WP_Error のほうが、のちの調査が楽です。

WP_Error の扱い方の関連項目

出典(一次情報)

タイトルとURLをコピーしました