wp_send_json_success()とwp_send_json_error()はsuccessの真偽とdataを分けて返す
公開日: 執筆:佐藤
WordPressのAjax処理からJSONを返すなら、成功時はwp_send_json_success()、失敗時はwp_send_json_error()を使います。JavaScript側は、最初にsuccessの真偽を確認し、その結果に応じてdataを読みます。
この二つの関数は、JSONを出力した後にPHPの処理を終了します。関数を呼んだ後へ別のHTMLや文字列を出力しないでください。返却形式を一つに決めることで、保存、検証、権限不足などの結果を同じ順序で処理できます。
successとdataの役割を分ける
WordPress 4.2.2のcore sourceでは、wp_send_json_success()はsuccessをtrueにし、wp_send_json_error()はfalseにします。引数へ値を渡した場合だけ、dataが追加されます。
| PHP側の呼出し | JSONの形 | 用途 |
|---|---|---|
wp_send_json_success() |
{"success":true} |
dataを返さず成功だけを伝える |
wp_send_json_success($data) |
{"success":true,"data":...} |
成功結果をdataへ入れる |
wp_send_json_error() |
{"success":false} |
dataを返さず失敗だけを伝える |
wp_send_json_error($data) |
{"success":false,"data":...} |
理由や入力項目をdataへ入れる |
successは処理結果の判定に使い、dataは結果に付随する値に使います。dataがあるかどうかだけで成功を判断すると、失敗理由を入れたresponseを成功と誤認します。
Ajax callbackは一つのresponseで終える
次は、入力したメモを保存する流れを示す説明用の仮例です。hookの登録とJavaScriptからの送信処理は省略しています。
function satolab_save_note() {
if ( ! check_ajax_referer( 'satolab_save_note', 'nonce', false ) ) {
wp_send_json_error( array(
'message' => '送信元を確認できません。',
) );
}
if ( ! current_user_can( 'edit_posts' ) ) {
wp_send_json_error( array(
'message' => '操作権限を確認できません。',
) );
}
$note = isset( $_POST['note'] )
? sanitize_text_field( wp_unslash( $_POST['note'] ) )
: '';
if ( '' === $note ) {
wp_send_json_error( array(
'field' => 'note',
'message' => 'メモを入力してください。',
) );
}
wp_send_json_success( array(
'message' => 'メモを受け付けました。',
) );
}
例では、nonce、操作権限、入力値を確認してから結果を返しています。実際の保存処理は省略しているため、保存済みの実装例ではありません。
各分岐でreturnを書いていませんが、wp_send_json_success()とwp_send_json_error()がresponseを出力して処理を終えます。関数の後へechoや別のresponseを置くと考えず、一つの分岐を一つのresponseで閉じます。
JavaScriptはsuccessを先に確認する
JavaScript側では、responseを受け取った後、successを先に判定します。次はresponseの読み分けだけを示す仮例です。
function handleSaveResponse(response) {
if (!response.success) {
showError(response.data && response.data.message
? response.data.message
: '処理を完了できませんでした。');
return;
}
showNotice(response.data && response.data.message
? response.data.message
: '処理を完了しました。');
}
通信できなかったことと、WordPressがsuccess: falseを返したことは別です。network error、応答形式の破損、PHP errorは通信側の処理で扱い、入力不足や操作不可など、callbackが判定した結果はsuccessで扱います。
同じ画面に複数のAjax機能がある場合も、成功時と失敗時のdata形式を機能ごとに決めます。message、field、更新後の値などを思いつきで混ぜず、JavaScriptが必要とする値だけを返してください。
WP_Errorはcodeとmessageの配列になる
wp_send_json_error()へWP_Errorを渡すと、error codeとmessageの組が配列としてdataへ入ります。
$result = satolab_validate_note();
if ( is_wp_error( $result ) ) {
wp_send_json_error( $result );
}
一件のerrorなら、responseは次の形になります。
{
"success": false,
"data": [
{
"code": "empty_note",
"message": "メモを入力してください。"
}
]
}
通常の配列を渡した場合と、WP_Errorを渡した場合では、dataの形が違います。JavaScript側がdata.messageを読む設計なら、PHP側でも通常の配列へ統一します。複数の検証errorを扱うためWP_Errorを渡すなら、JavaScript側はdataを配列として処理します。
どちらが正しいかではなく、response contractを一つに決めることが重要です。
wp_send_json()が出力と終了を担当する
二つの関数は、内部でwp_send_json()を呼びます。wp_send_json()はJSON用のContent-Typeを送り、値をwp_json_encode()で変換し、出力後に処理を終了します。
そのため、header()、echo json_encode()、die()をcallbackごとに重ねて書く必要はありません。独自の出力処理とWordPressの関数を混ぜると、JSONの前後へ不要な文字が入り、JavaScriptでresponseを読めなくなる原因になります。
開発を外部へ委託する場合は、PHPの関数名だけでなく、成功時と失敗時のJSON例を仕様として残してください。実装作業を任せても、画面が必要とするresponse contractは運用側でも確認できる状態にします。
最初の一手は、一つのAjax callbackについて、成功時と失敗時のJSONを一件ずつ書き出すことです。PHPとJavaScriptが同じsuccessとdataの形を前提にしているかを確認してから、処理を追加してください。
関連記事

