تصحيح أخطاء API بسرعة: لماذا يعيد PHP نص HTML بدلاً من JSON؟
\n\nهل سبق لك أن جلست في الساعة الثالثة فجرًا، تحدق في شاشة Postman الفارغة وتتساءل: "لماذا يعيد سكريبت PHP الخاص بي نص HTML بدلاً من JSON؟" إذا كان الأمر كذلك، فأنت لست وحدك. موضوع إرجاع JSON من سكريبت PHP على Stack Overflow حصد عشرات الآلاف من المشاهدات، وهذا ليس من قبيل الصدفة. كل مطور مبتدئ في الواجهة الخلفية يقع في نفس الأخطاء: نسيان الرؤوس، إخراج غير مرغوب فيه، نوع محتوى خاطئ.
\n\nفي هذه المقالة، لن نكتفي بنسخ إجابة من منتدى. سنقوم بتحليل كيفية إرجاع JSON من PHP بشكل صحيح وسريع وبدون مفاجآت. ستتعرف على لماذا قد يخذلك exit(json_encode($data))، وكيف توفر أجزاء من الثانية في عملية التسلسل، وماذا تفعل إذا تعطل JSON فجأة.
هل أنت مستعد؟ لنبدأ.
\n\nتشريح استجابة JSON الصحيحة
\n\nلنبدأ بالأساسيات. إليك كيف لا يجب أن تفعل:
\n\n<?php\n$data = ['status' => 'ok', 'message' => 'مرحباً!'];\necho json_encode($data);\n?>\n\nلماذا هذا سيء؟ أولاً، لا يوجد رأس Content-Type. قد يفسر المتصفح أو العميل الاستجابة على أنها HTML أو نص. ثانيًا، إذا كان هناك أي مسافة أو echo أو تحذير في الكود قبل ذلك، فسينكسر JSON.
القالب البسيط الصحيح يبدو هكذا:
\n\n<?php\nheader('Content-Type: application/json; charset=utf-8');\n$data = ['status' => 'ok', 'message' => 'مرحباً!'];\necho json_encode($data, JSON_UNESCAPED_UNICODE);\nexit;\n?>\n\nلاحظ استخدام JSON_UNESCAPED_UNICODE — فهو يحافظ على النص العربي مقروءًا، بدلاً من تحويله إلى \\u0645\\u0631\\u062D\\u0628\\u0627. و exit هو ضمان ضد أي إخراج عشوائي بعد الاستجابة.
الرؤوس: ليس فقط Content-Type
\n\nلـ تحسين أداء JSON، أضف رأسين إضافيين:
\n\nheader('Content-Type: application/json; charset=utf-8');\nheader('X-Content-Type-Options: nosniff');\nheader('Cache-Control: no-cache, must-revalidate');\n\nX-Content-Type-Options: nosniff يمنع المتصفح من "تخمين" نوع المحتوى — وهذا يعزز الأمان. أما Cache-Control فهو مفيد للبيانات الديناميكية، لضمان عدم تخزين العميل لاستجابة قديمة.
معالجة الأخطاء: عندما تفشل دالة json_encode
\n\nالدالة json_encode ترجع false عند الفشل. وهنا يبدأ الجزء المثير للاهتمام. إذا قمت ببساطة بـ echo json_encode($data) وحصلت على سلسلة فارغة — سيصاب العميل بالحيرة.
تحقق دائمًا من النتيجة:
\n\n$json = json_encode($data, JSON_UNESCAPED_UNICODE);\nif ($json === false) {\n http_response_code(500);\n echo json_encode(['error' => 'فشل ترميز JSON: ' . json_last_error_msg()]);\n exit;\n}\necho $json;\nexit;\n\nبالمناسبة، json_last_error_msg() سيعيد رسالة واضحة: "Malformed UTF-8 characters" أو "Inf and NaN cannot be JSON encoded". هذا سيوفر لك ساعات من التصحيح.
البيانات المتداخلة بعمق والتكرار
\n\nمشكلة أخرى هي المراجع الدائرية في الكائنات. إذا قمت بتمرير كائن به مراجع متبادلة، فستتسبب الدالة json_encode في خطأ. الحل: استخدام JSON_PARTIAL_OUTPUT_ON_ERROR أو تحويل الكائن إلى مصفوفة مسبقًا.
$json = json_encode($complexObject, JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR);\n\nولكن كن حذرًا: الإخراج الجزئي قد يكون غير مكتمل. من الأفضل إصلاح بنية البيانات.
\n\nتحسين أداء JSON في PHP
\n\nالآن ننتقل إلى الجزء الأكثر إثارة — كيفية تسريع إرجاع JSON من PHP.
\n\n1. التخزين المؤقت لـ JSON المسلسل
\n\nإذا كانت البيانات تتغير نادرًا (قواميس، إعدادات، قائمة مدن)، فلا تقم بتسلسلها في كل مرة. احفظ JSON الجاهز في ملف، Memcached