تعرف على خطأ "Headers already sent": عدوك الجديد (وصديقك)
\n\nإذا سبق لك البرمجة بلغة PHP، فبالتأكيد واجهت هذا الخطأ. يظهر فجأة، غالباً في أكثر الأوقات غير المناسبة - عندما تكون على وشك إنهاء السكربت. الرسالة مخيفة، حمراء اللون، وتجعلك تعتقد أن الكود بأكمله معطل. لكن في الحقيقة، هذا واحد من أكثر الأخطاء فائدة في PHP. إنه يعلمك كيفية التعامل الصحيح مع بروتوكول HTTP.
\n\nفي هذا الدليل التعليمي، سنشرح لماذا يظهر خطأ Headers already sent، وكيفية تشخيصه، والأهم من ذلك، كيفية إصلاحه بشكل نهائي. لن نكتفي بنسخ إجابة من Stack Overflow - بل سنفهم الجوهر. هيا بنا!
ما هي رؤوس HTTP ولماذا يعترض PHP عليها؟
\n\nقبل العلاج، يجب فهم التشريح. عندما يرسل PHP الرد إلى المتصفح، يفعل ذلك على مرحلتين:
\n\n- \n
- أولاً - الرؤوس (headers). هذه معلومات خدمية: نوع المحتوى (
Content-Type)، الترميز، الكوكيز، حالة الرد (200 OK، 404 Not Found). \n - ثانياً - نص الرد (body). هذا هو HTML نفسه، النص، JSON - ما يراه المستخدم. \n
المشكلة أن PHP لا يستطيع إرسال الرؤوس بعد أن بدأ في إرسال النص. إذا حاولت استدعاء header() بعد أن قمت بإخراج أي حرف (حتى مسافة)، سيظهر خطأ PHP:
Warning: Cannot modify header information - headers already sent by (output started at /path/to/file.php:12)\n\nهذا هو كل السحر. الخطأ ليس قاتلاً - إنه مجرد تحذير بأن دالة header() لم تعمل. لكن العواقب قد تكون خطيرة: لن يتم تنفيذ إعادة التوجيه، لن يتم تعيين الكوكيز، سيتعطل رد JSON.
\n\nأهم 5 أسباب لحدوث هذا الخطأ
\n\nدعنا نستعرض السيناريوهات الأكثر شيوعاً. هل تجد نفسك في أحدها؟
\n\n1. مسافة أو سطر فارغ قبل <?php
\n\nهذا كلاسيكي. تفتح الملف، وقبل علامة الفتح <?php توجد مسافة، سطر فارغ، أو حرف BOM (Byte Order Mark). يعتبر PHP هذا الحرف جزءاً من الإخراج - وتبدأ المشكلة.
// ❌ خطأ: مسافة قبل <?php\n <?php\nheader('Location: /new-page.php');\n?>\n\n// ✅ صحيح: لا توجد أحرف قبل <?php\n<?php\nheader('Location: /new-page.php');\n?>\n\n2. الإخراج عبر echo أو print قبل دالة header()
\n\nخطأ منطقي وشائع بين المبتدئين: إخراج شيء أولاً، ثم محاولة إعادة توجيه المستخدم.
\n\n<?php\necho "مرحباً بالعالم!";\nheader('Location: /thanks.php'); // ❌ خطأ: تم الإخراج بالفعل\n?>\n\n3. كود HTML قبل كتلة PHP
\n\nقد يحتوي الملف على كود مختلط: ترميز HTML أولاً، ثم منطق PHP مع دالة header().
\n\n<!DOCTYPE html>\n<html>\n<head>\n <title>موقعي</title>\n</head>\n<body>\n<?php\nheader('Location: /login.php'); // ❌ خطأ: تم إرسال HTML بالفعل\n?>\n</body>\n</html>\n\n4. أخطاء PHP ودوال مثل var_dump()
\n\nقد يقوم السكربت بإخراج تحذيرات أو معلومات تصحيح قبل استدعاء دالة header(). مثلاً، إذا كان display_errors مفعّلاً وقام PHP بإخراج warning.
<?php\nvar_dump($some_variable); // إخراج بيانات\nheader('Content-Type: application/json'); // ❌ خطأ\n?>\n\n5. أحرف غير مرئية في الملفات المضمنة (include/require)
\n\nتقوم بتضمين ملف باستخدام include أو require، وفي نهاية هذا الملف يوجد سطر فارغ إضافي أو مسافة بعد علامة الإغلاق ?>.
// config.php\n<?php\n$db_host = 'localhost';\n?>\n // ← هذه المسافة بعد ?> تفسد كل شيء!\n\nكيف تجد مصدر المشكلة: تشخيص خطوة بخطوة
\n\nالأهم من ذلك - الخطأ يشير دائماً إلى أين بدأ الإخراج بالضبط. اقرأ الرسالة بعناية