انتقل إلى محتوى الدرس
الدرس 50
دورة PHP

إدارة رؤوس HTTP والتحويلات ورموز الحالة والتخزين المؤقت للمخرجات في PHPPHP HTTP Headers Redirects Status Codes and Output Buffering

أرسل تحويلات المتصفح بـ Location ورموز الحالة وتنزيل الملفات، وامنع خطأ headers already sent عبر التخزين المؤقت ob_start في PHP 8.
أقسام الدرس
6
الأمثلة
6
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
0
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع

تتكون كل استجابة HTTP من رؤوس معلومات (Headers) يتبعها سطر فارغ ثم جسم الصفحة (Body)، وتتيح دالة header() في PHP إرسال هذه الرؤوس قبل بدء إرسال محتوى الصفحة.

  • تفرض قواعد بروتوكول HTTP إرسال جميع الرؤوس قبل إرسال أي بايت من جسم الصفحة (سواء وسم HTML أو echo أو حتى مسافة فارغة قبل <?php).
  • استخدم header("Content-Type: ...") أو Content-Disposition لإخبار المتصفح بنوع المحتوى أو إجباره على تنزيل ملف.
  • افتراضياً، يؤدي تكرار استدعاء header() بنفس اسم الرأس إلى استبدال القيمة السابقة ما لم تضبط المعامل الثاني $replace على false.

تضبط استدعاءات header() الثلاثة نوع المحتوى ورؤوس الأمان في أعلى السكريبت قبل أول أمر طباعة echo.

مخطط توضيحي: محاكي رؤوس HTTP والتحويلات والتخزين المؤقت للمخرجات في PHP
PHP
<?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
<?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
<?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 ثوانٍ.

مخطط تدفق التنفيذ العملي لقسم التحكم في الكاش والتحويل المؤقت بـ Cache-Control و Refresh في لغة PHP
PHP
<?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
<?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 /urlAlways follow with exit;
header("Location: /url", true, 301); exit;301 Permanent SEO RedirectBrowsers cache 301 redirects
http_response_code(404);Sets 404 Not Found statusCall before echoing error HTML
header("Cache-Control: no-store");Disables browser cachingEssential for private/auth pages
ob_start() / ob_get_clean()Buffers output in RAMPrevents premature body flush

PHP
<?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

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 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

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 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 ويرسلها إلى متصفح العميل بعد التنفيذ.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

من الفهم للتطبيق

مهامك قبل الاختبار

خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.

0/2مهام منجزة
  1. أنشئ ملف PHP محلياً ونفّذ المثال البرمجي المشروح في قسم كيف يرسل PHP معلومات استجابة HTTP للمتصفح للتحقق من المخرجات.

  2. بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم تحويل المسار بـ Location وأهمية إيقاف التنفيذ بـ exit وقارن مخرجات التنفيذ.

تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.

مساحة التحدي

اختبر فهمك.
ووصلها للإتقان.

كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.

8أسئلة 1أنواع تحديات 100%هدف الإتقان
تصحيح تلقائي. فرص بلا حدود.

أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.

الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.

لمحة عن التحدي8 أسئلة تنتظرك
01

لماذا يجب استدعاء exit; مباشرة بعد التعليمة header("Location: /login.php");؟

لا توقف دالة header() تنفيذ السكريبت، لذا سيعمل الكود السري أسفلها إذا لم تستدعِ exit.

02

ما السبب وراء ظهور تحذير PHP الشهير: "Cannot modify header information - headers already sent"؟

في بروتوكول HTTP يجب إرسال جميع الرؤوس قبل بدء جسم الصفحة.

03

ما رمز حالة HTTP الذي ترسله header("Location: /dashboard") افتراضياً عند عدم تحديد رمز حالة؟

يضبط PHP رمز الحالة افتراضياً على 302 عند إرسال رأس Location.

04

كيف يمكنك معرفة اسم الملف ورقم السطر الدقيق الذي بدأ إرسال المخرجات مبكراً عند تتبع أخطاء الرؤوس؟

تملأ الدالة headers_sent($file, $line) المتغيرين بالمرجع باسم الملف ورقم السطر المسببين للإرسال.

05

ماذا تفعل الدالة ob_get_clean() عندما يكون التخزين المؤقت للمخرجات نشطاً؟

تجمع ob_get_clean() بين قراءة المحتوى كنص ومسح المخزن المؤقت في خطوة واحدة.

06

لماذا ينص معيار PSR-12 على عدم كتابة وسم الإغلاق ?> في نهاية ملفات PHP الصرفة؟

أي مسافة أو سطر جديد بعد ?> يُعامل فوراً كمخرجات HTML فيمنع إرسال الرؤوس لاحقاً.

07

أي رأس تأمر المتصفح بعدم حفظ صفحة حساب حساسة في ذاكرة التخزين المؤقت (الكاش)؟

تمنع رأس Cache-Control: no-store المتصفح من تخزين الاستجابة.

08

ماذا ترجع الدالة http_response_code() عند استدعائها بدون أي معاملات؟

بدون معاملات تعمل الدالة كقارئ وترجع رمز الحالة الرقمي المضبوط حالياً.