في هذا الدرس 6تصفّح المواضيع
تتكون كل استجابة HTTP من رؤوس معلومات (Headers) يتبعها سطر فارغ ثم جسم الصفحة (Body)، وتتيح دالة header() في PHP إرسال هذه الرؤوس قبل بدء إرسال محتوى الصفحة.
- تفرض قواعد بروتوكول HTTP إرسال جميع الرؤوس قبل إرسال أي بايت من جسم الصفحة (سواء وسم HTML أو
echoأو حتى مسافة فارغة قبل<?php). - استخدم
header("Content-Type: ...")أوContent-Dispositionلإخبار المتصفح بنوع المحتوى أو إجباره على تنزيل ملف. - افتراضياً، يؤدي تكرار استدعاء
header()بنفس اسم الرأس إلى استبدال القيمة السابقة ما لم تضبط المعامل الثاني$replaceعلىfalse.
تضبط استدعاءات header() الثلاثة نوع المحتوى ورؤوس الأمان في أعلى السكريبت قبل أول أمر طباعة echo.
<?php
header("Content-Type: text/plain; charset=UTF-8");
header("X-Content-Type-Options: nosniff");
header("X-Powered-By: CloseTag-Engine");
echo "Response headers configured before body output.\n";
echo "Headers sent? " . (headers_sent() ? "Yes" : "No") . "\n";
يوجه إرسال رأس Location: المتصفح للانتقال إلى رابط آخر، ولكنه لا يوقف محرك PHP تلقائياً عن إكمال تنفيذ بقية أسطر السكريبت.
- استدعِ دائماً
exit;في السطر التالي مباشرة بعدheader("Location: ...")! - يُعد نسيان
exit;بعد تحويل غير المسجلين ثغرة أمنية خطيرة؛ لأن PHP سيواصل تنفيذ كود الصفحة المحمية ويرسل محتواها بالكامل في جسم الاستجابة. - افتراضياً، ترسل
header("Location: /target")رمز الحالة المؤقت302 Foundما لم تحدد رمز3xxآخر.
لأن exit; تنهي تنفيذ السكريبت فوراً بعد إرسال رأس التحويل، فلن يصل التنفيذ أبداً إلى محتوى لوحة التحكم السرية بالأسفل.
<?php
$isAuthenticated = false;
if (!$isAuthenticated) {
header("Location: /login.php", true, 302);
echo "Redirecting to /login.php (302)...\n";
exit;
}
echo "Secret Admin Dashboard Content\n";
تتيح الدالة http_response_code($code) قراءة أو ضبط رمز حالة استجابة HTTP (مثل 200 أو 404 أو 500) مباشرة دون كتابة نص البروتوكول يدوياً.
- إن استدعاء
http_response_code(404)قبل عرض صفحة "غير موجود" يضمن إبلاغ المتصفحات ومحركات البحث بأن الرابط غير موجود فعلياً. - يرجع استدعاء
http_response_code()بدون معاملات رمز الحالة الرقمي المضبوط حالياً. - لا ترجع أبداً رمز النجاح
200 OKعند عرض صفحة خطأ أو رفض صلاحية الوصول.
تضبط http_response_code(404) حالة الاستجابة على 404، ويؤكد استدعاؤها بدون معاملات أن الرمز النشط هو 404.
<?php
$articleFound = false;
if (!$articleFound) {
http_response_code(404);
}
echo "Current HTTP Status: " . http_response_code() . "\n";
يجب أن ترسل لوحات التحكم الخاصة وخطوات الدفع رؤوس Cache-Control صريحة لمنع المتصفحات أو الخوادم الوسيطة من تخزين بيانات المستخدم الحساسة مؤقتاً.
- استخدم
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0")في الصفحات الخاصة لمنع ظهورها عند الضغط على زر الرجوع بعد تسجيل الخروج. - للموارد العامة غير الحساسة، استخدم
header("Cache-Control: public, max-age=3600")للتخزين المؤقت لمدة ساعة. - يمكن إرسال تحويل مؤجل زمنياً عبر
header("Refresh: 5; url=/dashboard.php")للانتظار 5 ثوانٍ قبل التحويل.
تمنع رأس Cache-Control: no-store حفظ صفحة الدفع في ذاكرة المتصفح، بينما توجه Refresh: 3 المتصفح للانتقال لصفحة الطلبات بعد 3 ثوانٍ.
<?php
// Prevent browser caching on sensitive billing page:
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Pragma: no-cache");
header("Refresh: 3; url=/orders.php");
echo "Payment complete! Redirecting to orders in 3 seconds...\n";
يظهر التحذير الشهير Cannot modify header information - headers already sent عندما يرسل PHP أي مخرجات نصية قبل استدعاء header() أو setcookie() أو session_start().
- استدعِ
headers_sent($file, $line)لمعرفة اسم الملف ورقم السطر الدقيق الذي تسبب في بدء إرسال المخرجات مبكراً. - احذف أي مسافات أو ترميز BOM قبل وسم البداية
<?php، ولا تكتب وسم الإغلاق?>في نهاية ملفات PHP الصرفة. - يتيح استدعاء
ob_start()في بداية السكريبت حجز المخرجات مؤقتاً في الذاكرة بحيث يظل إرسال الرؤوس متاحاً حتى تفريغ المخزن بـob_end_flush().
تحجز ob_start() مخرجات echo في الذاكرة المؤقتة، مما يسمح بتنفيذ header() بأمان قبل سحب المحتوى ومسح المخزن عبر ob_get_clean().
<?php
ob_start();
echo "<h1>Buffered Heading</h1>\n";
// Because ob_start() holds output in memory, header() still succeeds:
header("X-Buffered-Render: true");
$html = ob_get_clean();
echo "Captured " . strlen($html) . " bytes safely.\n";
يتيح إتقان رؤوس HTTP القياسية التحكم الكامل في التحويلات ونوع المحتوى وتنزيل الملفات والتخزين المؤقت.
- رتّب منطق الصفحة دائماً بحيث يتم التحقق وتحديث الجلسة والتحويل قبل تضمين قوالب HTML.
- استخدم
ob_get_clean()عندما تريد التقاط مخرجات قالب PHP داخل متغير نصي (مثل تجهيز قالب رسالة بريد إلكتروني). - أتبع كل رأس تحويل
Locationبتعليمةexit;صريحة دائماً.
يتحقق الشرط !headers_sent($file, $line) من عدم إرسال الرؤوس مسبقاً قبل ضبط رمز الحالة ونوع محتوى JSON.
| الأمر في PHP | الأثر في بروتوكول HTTP | القاعدة الأساسية |
|---|---|---|
header("Location: /url"); exit; | 302 Redirect to /url | Always follow with exit; |
header("Location: /url", true, 301); exit; | 301 Permanent SEO Redirect | Browsers cache 301 redirects |
http_response_code(404); | Sets 404 Not Found status | Call before echoing error HTML |
header("Cache-Control: no-store"); | Disables browser caching | Essential for private/auth pages |
ob_start() / ob_get_clean() | Buffers output in RAM | Prevents premature body flush |
<?php
if (!headers_sent($file, $line)) {
http_response_code(200);
header("Content-Type: application/json; charset=UTF-8");
echo json_encode(["ok" => true, "status" => http_response_code()]) . "\n";
} else {
echo "Headers already sent at $file:$line\n";
}
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
يتيح إتقان رؤوس HTTP القياسية التحكم الكامل في التحويلات ونوع المحتوى وتنزيل الملفات والتخزين المؤقت. رتّب منطق الصفحة دائماً بحيث يتم التحقق وتحديث الجلسة والتحويل قبل تضمين قوالب HTML. استخدم ob_get_clean() عندما تريد التقاط مخرجات قالب PHP داخل متغير نصي (مثل تجهيز قالب رسالة بريد إلكتروني). أتبع كل رأس تحويل Location بتعليمة exit; صريحة دائماً.
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 Headers & Redirects التحويلات و header()
- أرسل تحويلات المتصفح بـ Location ورموز الحالة وتنزيل الملفات، وامنع خطأ headers already sent عبر التخزين المؤقت ob_start في PHP 8.
- للمراجعة
- 02 How PHP Sends HTTP Response Headers كيف يرسل PHP معلومات استجابة HTTP للمتصفح
- المفهوم الأساسي لقسم كيف يرسل PHP معلومات استجابة HTTP للمتصفح في لغة PHP الحديثة.
- للمراجعة
- 03 URL Redirection with Location and exit تحويل المسار بـ Location وأهمية إيقاف التنفيذ بـ exit
- الصياغة البرمجية والتطبيق العملي المباشر لقسم تحويل المسار بـ Location وأهمية إيقاف التنفيذ بـ exit.
- للمراجعة
- 04 Setting Codes with http_response_code ضبط رموز الحالة 200 و 301 و 404 بـ http_response_code
- قواعد التحقق وأفضل الممارسات القياسية الخاصة بقسم ضبط رموز الحالة 200 و 301 و 404 بـ http_response_code.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 PHP PHP
- PHP: Hypertext Preprocessor
- لغة البرمجة النصية على جانب الخادم لبناء تطبيقات الويب الديناميكية وواجهات البرمجة.
- للمراجعة
- 02 CLI CLI
- Command-Line Interface
- واجهة سطر الأوامر التي تتيح تشغيل ملفات PHP مباشرة عبر الطرفية.
- للمراجعة
- 03 FPM FPM
- FastCGI Process Manager
- مدير عمليات FastCGI عالي الأداء لمعالجة طلبات خادم الويب في PHP.
- للمراجعة
- 04 HTML HTML
- HyperText Markup Language
- لغة الترميز القياسية التي يولدها محرك PHP ويرسلها إلى متصفح العميل بعد التنفيذ.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
أنشئ ملف PHP محلياً ونفّذ المثال البرمجي المشروح في قسم كيف يرسل PHP معلومات استجابة HTTP للمتصفح للتحقق من المخرجات.
-
بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم تحويل المسار بـ Location وأهمية إيقاف التنفيذ بـ exit وقارن مخرجات التنفيذ.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي8 أسئلة تنتظرك +
لماذا يجب استدعاء exit; مباشرة بعد التعليمة header("Location: /login.php");؟
لا توقف دالة header() تنفيذ السكريبت، لذا سيعمل الكود السري أسفلها إذا لم تستدعِ exit.
ما السبب وراء ظهور تحذير PHP الشهير: "Cannot modify header information - headers already sent"؟
في بروتوكول HTTP يجب إرسال جميع الرؤوس قبل بدء جسم الصفحة.
ما رمز حالة HTTP الذي ترسله header("Location: /dashboard") افتراضياً عند عدم تحديد رمز حالة؟
يضبط PHP رمز الحالة افتراضياً على 302 عند إرسال رأس Location.
كيف يمكنك معرفة اسم الملف ورقم السطر الدقيق الذي بدأ إرسال المخرجات مبكراً عند تتبع أخطاء الرؤوس؟
تملأ الدالة headers_sent($file, $line) المتغيرين بالمرجع باسم الملف ورقم السطر المسببين للإرسال.
ماذا تفعل الدالة ob_get_clean() عندما يكون التخزين المؤقت للمخرجات نشطاً؟
تجمع ob_get_clean() بين قراءة المحتوى كنص ومسح المخزن المؤقت في خطوة واحدة.
لماذا ينص معيار PSR-12 على عدم كتابة وسم الإغلاق ?> في نهاية ملفات PHP الصرفة؟
أي مسافة أو سطر جديد بعد ?> يُعامل فوراً كمخرجات HTML فيمنع إرسال الرؤوس لاحقاً.
أي رأس تأمر المتصفح بعدم حفظ صفحة حساب حساسة في ذاكرة التخزين المؤقت (الكاش)؟
تمنع رأس Cache-Control: no-store المتصفح من تخزين الاستجابة.
ماذا ترجع الدالة http_response_code() عند استدعائها بدون أي معاملات؟
بدون معاملات تعمل الدالة كقارئ وترجع رمز الحالة الرقمي المضبوط حالياً.