چرا خطاهای AJAX شما بیصدا ناپدید میشوند؟ راهنمای wp_send_json_error
تابع wp_send_json_error برای ارسال پاسخ خطا JSON در وردپرس؛ بررسی پارامترها، کد وضعیت، پیام مناسب و اشتباهات رایج در مدیریت خطا.
چرا مدیریت خطای AJAX حیاتی است؟
در هر برنامه وردپرس، خطاها رخ میدهند. اگر این خطاها بهدرستی به سمت کلاینت منتقل نشوند، کاربر بدون بازخورد میماند، توسعهدهنده نمیتواند مشکل را ریشهیابی کند و تجربه کاربری تضعیف میشود. تابعwp_send_json_error() این مسئله را حل میکند. این تابع پاسخ خطا را با ساختار استاندارد، کد وضعیت HTTP مناسب و پیام قابلفهم ارسال میکند. سمت کلاینت میتواند این پاسخ را تشخیص دهد و به کاربر نمایش دهد.
تابع wp_send_json_error چیست؟
تابعwp_send_json_error() یک تابع هسته وردپرس است که در فایل wp-includes/functions.php تعریف شده است. این تابع یک پاسخ JSON با ساختار خطا ارسال میکند و پردازش PHP را متوقف میسازد.
نکته مهم این است که کلید success در پاسخ این تابع روی false قرار میگیرد و دادهها در کلید data قرار میگیرند. این ساختار متضاد با wp_send_json_success است و امکان تفکیک آسان را در سمت JavaScript فراهم میکند.
برای ارسال پاسخ موفق، از wp_send_json_success استفاده کنید که در صفحه wp_send_json_success به تفصیل بررسی شده است.
امضای تابع و پارامترها
امضای این تابع بهشکل زیر است:function wp_send_json_error( $data = null, $status_code = null, $options = 0 ) {
$response = array( 'success' => false );
if ( null !== $data ) {
$response['data'] = $data;
}
wp_send_json( $response, $status_code, $options );
}
پارامتر اول (data) دادهای است که در پاسخ خطا ارسال میشود. معمولاً آرایهای حاوی پیام خطا یا کد خطا است.
پارامتر دوم (status_code) کد وضعیت HTTP است. اگر null باشد، کد پیشفرض (۲۰۰) استفاده میشود که در AJAX رایج است.
پارامتر سوم (options) تنظیمات wp_json_encode است که در وردپرس ۵.۶ به بعد اضافه شده است.
سازوکار داخلی تابع
تابعwp_send_json_error ابتدا یک آرایه با کلید success روی false میسازد. اگر دادهای پاس داده شده باشد، آن را در کلید data قرار میدهد.
سپس تابع wp_send_json را فراخوانی میکند که:
- هدر Content-Type: application/json; charset=utf-8 را ارسال میکند
- داده را به JSON تبدیل میکند
- خروجی را چاپ میکند
- با wp_die() پردازش را متوقف میکند
نکته مهم: کد وضعیت HTTP تنها در صورتی که پارامتر دوم پاس داده شود، در هدر ارسال میشود. مقدار پیشفرض null باعث میشود که کد وضعیت ۲۰۰ ارسال شود که در AJAX استاندارد است.
ساختار پاسخ JSON
خروجی این تابع بهشکل زیر است:{
"success": false,
"data": {
"code": "invalid_nonce",
"message": "درخواست نامعتبر است",
"status": 403
}
}
کلید success همیشه false است. کلید data در صورت پاس داده شدن، شامل اطلاعات خطا است.
الگوی حرفهای این است که در data، سه فیلد قرار دهید:
- code: کد خطای داخلی (رشته یا عدد)
- message: پیام قابلنمایش به کاربر
- status: کد وضعیت HTTP یا وضعیت خطا
کدهای وضعیت HTTP
انتخاب کد وضعیت مناسب، به سمت کلاینت کمک میکند که ماهیت خطا را بفهمد: -400 Bad Request: درخواست نامعتبر یا داده ناقص
- 401 Unauthorized: کاربر وارد نشده
- 403 Forbidden: کاربر وارد شده اما دسترسی ندارد
- 404 Not Found: منبع موردنظر پیدا نشد
- 422 Unprocessable Entity: داده معتبر نیست
- 429 Too Many Requests: درخواستهای متعدد
- 500 Internal Server Error: خطای سرور
نمونه استفاده:
if ( ! check_ajax_referer( 'myplugin_nonce', 'nonce', false ) ) {
wp_send_json_error(
array( 'message' => 'درخواست نامعتبر است' ),
403
);
}
نکته مهم: در AJAX سنتی، بسیاری از افزونهها کد وضعیت را ارسال نمیکنند و از کد ۲۰۰ استفاده میکنند. اما ارسال کد وضعیت صحیح، امکان پردازش دقیقتر در سمت کلاینت را فراهم میکند.
کاربردهای عملی در افزونه
مدیریت خطای پردازش سفارش:add_action( 'wp_ajax_myplugin_process_order', 'myplugin_process_order_handler' );
function myplugin_process_order_handler() {
if ( ! check_ajax_referer( 'myplugin_order_nonce', 'nonce', false ) ) {
wp_send_json_error( array(
'code' => 'invalid_nonce',
'message' => 'نشست شما منقضی شده است. صفحه را بازخوانی کنید.',
), 403 );
}
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( array(
'code' => 'insufficient_permissions',
'message' => 'دسترسی کافی ندارید',
), 403 );
}
$order_id = isset( $_POST['order_id'] ) ? absint( $_POST['order_id'] ) : 0;
if ( ! $order_id ) {
wp_send_json_error( array(
'code' => 'missing_order_id',
'message' => 'شناسه سفارش نامعتبر است',
), 400 );
}
$order = wc_get_order( $order_id );
if ( ! $order ) {
wp_send_json_error( array(
'code' => 'order_not_found',
'message' => 'سفارش پیدا نشد',
), 404 );
}
try {
myplugin_process_order( $order );
wp_send_json_success( array( 'order_id' => $order_id ) );
} catch ( Exception $e ) {
wp_send_json_error( array(
'code' => 'processing_failed',
'message' => 'خطا در پردازش: ' . $e->getMessage(),
), 500 );
}
}
مدیریت خطای اعتبارسنجی فرم:
function myplugin_validate_form_handler() {
check_ajax_referer( 'myplugin_form_nonce', 'nonce' );
$errors = array();
$email = isset( $_POST['email'] ) ? sanitize_email( $_POST['email'] ) : '';
if ( ! is_email( $email ) ) {
$errors['email'] = 'ایمیل نامعتبر است';
}
$name = isset( $_POST['name'] ) ? sanitize_text_field( $_POST['name'] ) : '';
if ( empty( $name ) ) {
$errors['name'] = 'نام الزامی است';
}
if ( ! empty( $errors ) ) {
wp_send_json_error( array(
'code' => 'validation_failed',
'message' => 'لطفاً خطاها را بررسی کنید',
'errors' => $errors,
), 422 );
}
wp_send_json_success( array( 'message' => 'فرم با موفقیت ثبت شد' ) );
}
پردازش سمت JavaScript:
jQuery.post(
mypluginData.ajaxUrl,
formData,
function( response ) {
if ( response.success ) {
showSuccess( response.data.message );
return;
}
// نمایش پیام خطای کلی
showError( response.data.message );
// نمایش خطاهای فیلد به فیلد
if ( response.data.errors ) {
jQuery.each( response.data.errors, function( field, message ) {
jQuery( '[name="' + field + '"]' ).addClass( 'has-error' );
jQuery( '[name="' + field + '"]' ).next( '.error-message' ).text( message );
} );
}
}
);
اشکالزدایی خطاهای AJAX
یکی از مشکلات رایج در AJAX، ناپدید شدن خطاها است. برای اشکالزدایی:add_action( 'wp_ajax_myplugin_debug_test', 'myplugin_debug_handler' );
function myplugin_debug_handler() {
if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
wp_send_json_error( array( 'message' => 'حالت دیباگ غیرفعال است' ), 400 );
}
if ( ! check_ajax_referer( 'myplugin_debug_nonce', 'nonce', false ) ) {
wp_send_json_error( array(
'code' => 'nonce_failed',
'message' => 'nonce نامعتبر',
'received_nonce' => isset( $_POST['nonce'] ) ? $_POST['nonce'] : 'missing',
), 403 );
}
wp_send_json_success( array( 'message' => 'همه چیز درست است' ) );
}
نکته مهم: در محیط تولید، اطلاعات دیباگ نباید در پاسخ نمایش داده شوند. این کد باید تنها در محیط توسعه فعال باشد.
نکات امنیتی و اشتباهات رایج
اشتباه اول، نبود کد خطا است. اگر کد خطا در پاسخ نباشد، سمت کلاینت نمیتواند خطا را تفکیک کند. اشتباه دوم، نبود پیام مناسب است. پیامهای عمومی مانند "خطا" به کاربر کمک نمیکنند. پیام باید قابلفهم و راهنما باشد. اشتباه سوم، نشت اطلاعات حساس است. هرگز پیام خطای داخلی سرور (مانند مسیر فایل یا پیام پایگاه داده) را مستقیم به کاربر ارسال نکنید. این اطلاعات میتواند به مهاجم کمک کند. اشتباه چهارم، نبود شرط است. اگرwp_send_json_error بدون شرط فراخوانی شود، پردازش متوقف میشود و ممکن است منطق بعدی از دست برود.
اشتباه پنجم، نبود escape در خروجی است. اگر پیام خطا شامل داده کاربر است، باید با esc_html یا wp_kses_post پاکسازی شود.
اشتباه ششم، نبود تست است. باید در همه سناریوهای خطا (nonce نامعتبر، دسترسی ناکافی، داده ناقص، خطای سرور) تست کنید.
اشتباه هفتم، نبود لاگگیری است. برای خطاهای حساس، علاوه بر پاسخ به کاربر، باید لاگ سرور نیز ثبت شود:
if ( is_wp_error( $result ) ) {
error_log( sprintf(
'[myplugin] Order processing failed: %s | Order ID: %d',
$result->get_error_message(),
$order_id
) );
wp_send_json_error( array(
'code' => 'processing_failed',
'message' => 'خطا در پردازش سفارش. لطفاً با پشتیبانی تماس بگیرید.',
), 500 );
}
تحلیل فنی پیشرفته
در نگاه مهندسی، تابعwp_send_json_error() یک نقطه معماری در لایه AJAX Response است که بر چند جنبه از سیستم اثر میگذارد. لایه اول لایه Error Contract است. این تابع یک قرارداد مشخص برای پاسخ خطا ایجاد میکند که شامل کلید success روی false و دادههای خطا است.
لایه دوم لایه Error Categorization است. استفاده از کدهای وضعیت HTTP و کدهای خطای داخلی، امکان دستهبندی دقیق خطاها را فراهم میکند.
لایه سوم لایه Security است. یکی از اصول امنیتی، عدم نشت اطلاعات داخلی است. پیامهای خطا باید عمومی باشند اما در لاگ سرور، اطلاعات کامل ثبت شود.
لایه چهارم لایه Observability است. ترکیب پاسخ JSON با لاگ سرور، امکان ردیابی خطاها را در محیط تولید فراهم میکند.
لایه پنجم لایه Client-Side Processing است. ساختار پاسخ استاندارد، امکان پردازش دقیق در سمت JavaScript را فراهم میکند.
لایه ششم لایه Multisite است. در شبکههای Multisite، پیام خطا باید در زمینه هر سایت خاص باشد.
لایه هفتم لایه Performance است. JSON سبک است و پردازش آن سریع است.
لایه هشتم لایه Testing است. تستهای End-to-End باید همه سناریوهای خطا را پوشش دهند.
مفاهیم پایهای Error Handling در Exception Handling در ویکیپدیا توضیح داده شده است.
برای مطالعه بیشتر روی توابع مرتبط، میتوانید به راهنمای wp_send_json_success، راهنمای wp_send_json، راهنمای هوک wp_ajax، راهنمای هوک wp_ajax_nopriv، راهنمای check_ajax_referer، راهنمای wp_verify_nonce و راهنمای current_user_can مراجعه کنید.
پرسشهای پرتکرار
تفاوتwp_send_json_error و wp_send_json_success چیست؟ اولی پاسخ خطا و دومی پاسخ موفق ارسال میکند.
آیا این تابع پردازش PHP را متوقف میکند؟ بله، با wp_die پردازش را متوقف میسازد.
آیا باید کد وضعیت HTTP پاس داد؟ توصیه میشود، چرا که به سمت کلاینت در تفکیک خطاها کمک میکند.
آیا پیام خطا باید برای کاربر نمایش داده شود؟ بله، اما باید قابلفهم و بدون افشای اطلاعات حساس باشد.
چطور خطاها را برای اشکالزدایی ثبت کنیم؟ با error_log یا ابزارهای لاگ سرور.
نتیجه و مسیر ادامه
تابعwp_send_json_error() ابزار استاندارد وردپرس برای ارسال پاسخ خطا در AJAX است. استفاده درست از آن یعنی پاس دادن کد خطا، پیام قابلفهم، کد وضعیت HTTP مناسب، عدم افشای اطلاعات حساس و لاگگیری برای اشکالزدایی. اشتباههای کوچک در این تابع اغلب به ناپدید شدن خطاها یا افشای اطلاعات منجر میشوند.
اگر این تابع را در پروژهای واقعی به کار بردهاید و رفتار غیرمنتظرهای دیدهاید — بهخصوص در ترکیب با افزونههای کش یا در REST API — تجربهتان میتواند راهگشای دیگران باشد. کدام بخش بیشترین زمان را از شما گرفت؟ دیدگاه خود را بنویسید.