أخطاء التوجيه في PHP: 5 أخطاء قاتلة وكيفية تجنبها

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا إعادة التوجيه في PHP ليست مجرد header('Location:')

\n\n

كل من كتب كود PHP ولو مرة واحدة، واجه مهمة إعادة توجيه المستخدم إلى صفحة أخرى. قد يبدو الأمر بسيطًا: سطر واحد header('Location: /new-page'); وينتهي الأمر. لكن في الواقع، تتحول هذه الآلية البسيطة إلى صداع لآلاف المطورين. ليس من قبيل الصدفة أن سؤال «How do I make a redirect in PHP?» على Stack Overflow حصد ملايين المشاهدات.

\n\n

المشكلة أن إعادة التوجيه في PHP ليست مجرد استدعاء دالة، بل هي عملية كاملة يمكن تعطيلها بسهولة. هل سبق ورأيت خطأ «Cannot modify header information»؟ أو لاحظت أن التوجيه يعمل لكن الصفحة لا تزال تُحمّل؟ أو الأسوأ من ذلك، واجهت أن التوجيه لا يعمل إطلاقًا ويظهر للمستخدم صفحة فارغة؟

\n\n

في هذا المقال، سنحلل 5 من أكثر الأخطاء شيوعًا عند إنشاء إعادة توجيه في PHP، ونتعلم كيفية إصلاحها، ونعرف كيف نجعل التوجيه آمنًا وموثوقًا. هيا بنا!

\n\n

الخطأ رقم 1: التوجيه بعد إخراج المحتوى (Header already sent)

\n\n

جوهر المشكلة

\n

الخطأ الأكثر شيوعًا بين المبتدئين هو محاولة إرسال رأس HTTP Location بعد أن تم إرسال كود HTML أو حتى مسافة واحدة إلى المتصفح. يعرض PHP خطأ فادحًا: «Cannot modify header information - headers already sent».

\n\n

لماذا يحدث هذا؟

\n

بروتوكول HTTP مصمم بحيث يجب إرسال الرؤوس (headers) قبل محتوى الاستجابة. بمجرد أن يخرج أي شيء إلى الشاشة (عبر echo، print، أو حتى سطر فارغ قبل <?php)، يتم تثبيت الرؤوس ولا يمكن تغييرها.

\n\n

مثال على الخطأ

\n
<?php\necho "مرحبًا!";\nheader('Location: /dashboard.php'); // خطأ: تم إرسال الرؤوس بالفعل\n?>
\n\n

كيفية الإصلاح

\n
    \n
  • القاعدة رقم 1: استدعِ header() قبل أي إخراج، بما في ذلك المسافات و HTML
  • \n
  • القاعدة رقم 2: تأكد من عدم وجود مسافات أو أسطر فارغة قبل <?php أو بعد ?> في ملف PHP الخاص بك
  • \n
  • القاعدة رقم 3: استخدم التخزين المؤقت للإخراج (output buffering) إذا كان لا بد من الإخراج المبكر
  • \n
\n\n
<?php\n// الصحيح: التوجيه قبل أي إخراج\nheader('Location: /dashboard.php');\nexit;\n?>
\n\n

التخزين المؤقت للإخراج (طريقة متقدمة):

\n
<?php\nob_start(); // تشغيل التخزين المؤقت\necho "محتوى مؤقت";\nheader('Location: /dashboard.php');\nob_end_flush(); // إرسال كل شيء دفعة واحدة\nexit;\n?>
\n\n

الخطأ رقم 2: نسيان exit (أو die) بعد التوجيه

\n\n

جوهر المشكلة

\n

استدعاء header('Location: ...') لا يوقف تنفيذ السكربت تلقائيًا. يستمر PHP في معالجة الكود بعدها، والمتصفح بعد استلام الرأس يبدأ بتحميل الصفحة الجديدة. لكن ماذا لو كان بعد التوجيه كود مكلف للموارد، أو الأسوأ من ذلك، كود يعدل البيانات في قاعدة البيانات؟

\n\n

مثال على الخطأ

\n
<?php\nheader('Location: /success.php');\n// المستخدم تم توجيهه بالفعل، لكن PHP لا يزال يعمل!\nupdate_user_balance($userId, -1000); // خطير: خصم رصيد\nsend_email_to_admin("المستخدم قام بعملية شراء");\n?>
\n\n

كيفية الإصلاح

\n

استخدم دائمًا exit (أو die) فورًا بعد استدعاء header(). هذا يضمن إنهاء السكربت وعدم تنفيذ أي كود زائد.

\n\n
<?php\nheader('Location: /success.php');\nexit; // إيقاف تام للسكربت\n// الكود التالي لن يتم تنفيذه\nupdate_user_balance($userId, -1000);\n?>
\n\n

الخطأ رقم 3: عنوان URL غير صحيح (نسبي مقابل مطلق)

\n\n

جوهر المشكلة

\n

معيار HTTP يتطلب أن تكون قيمة رأس Location عبارة عن عنوان URL كامل (مطلق) أو مسار نسبي يبدأ بـ "/". استخدام مسارات نسبية غير صحيحة قد يؤدي إلى توجيه المستخدم إلى صفحة خاطئة أو عدم عمل التوجيه إطلاقًا.

المدونات

توصيات الكتب