في هذا الدرس 6تصفّح المواضيع
عندما يعالج سكريبت PHP طلب POST ويطبع صفحة HTML مباشرة في نفس الاستجابة، يبقى آخر طلب مسجل في ذاكرة المتصفح هو طلب POST نفسه.
- إذا ضغط المستخدم على زر تحديث الصفحة ، يعيد المتصفح إرسال نفس بيانات
POSTمرة ثانية للخادم. - في المتاجر الإلكترونية وأنظمة الحجز، يؤدي تكرار إرسال
POSTإلى خصم المبلغ مرتين أو إدراج سجلات مكررة في قاعدة البيانات. - القاعدة الذهبية: لا تعرض صفحة HTML النهائية مباشرة كرد على طلب
POSTأبداً!
نظراً لعدم إجراء تحويل بعد معالجة طلب POST، فإن تحديث الصفحة يعيد تنفيذ كود الإضافة ويكرر الطلب.
<?php
$method = "POST";
if ($method === "POST") {
// Anti-pattern: rendering HTML directly without redirecting
echo "Order saved! (Danger: Pressing F5 will submit POST again!)\n";
}
يقسم نمط Post/Redirect/Get (PRG) معالجة النموذج إلى طلبين منفصلين بحيث يستقر المتصفح دائماً على رابط GET آمن قابل للتحديث.
- الخطوة 1 (POST): يرسل المتصفح البيانات عبر
POST، فيتحقق PHP منها ويحفظها ويخزن رسالة تنبيه في$_SESSIONثم يرد برأس تحويل. - الخطوة 2 (Redirect): يستقبل المتصفح رأس
Locationويقوم تلقائياً بإرسال طلبGETجديد للرابط المحدد. - الخطوة 3 (GET): يعرض PHP الصفحة عبر طلب
GET، ويصبح الضغط على مجرد تحديث آمن لصفحة العرض فقط.
يحفظ فرع POST رسالة النجاح داخل $_SESSION ويحول المتصفح فوراً إلى طلب GET /profile.php.
<?php
session_start();
$method = $_SERVER["REQUEST_METHOD"] ?? "POST";
if ($method === "POST") {
$_SESSION["flash_notice"] = "Profile updated successfully.";
header("Location: /profile.php", true, 303);
echo "Step 1 POST complete -> Redirecting (303) to GET /profile.php\n";
}
رغم أن الرمز 302 يعمل في أغلب المتصفحات، إلا أن معيار HTTP القياسي يخصص الرمز 303 See Other تحديداً لتحويل طلب POST إلى صفحة عرض GET.
- يأمر الرمز
303 See Otherالمتصفح صراحةً بفتح رابطLocationالجديد باستخدام طريقةGETحصراً. - في المقابل، يمنع الرمزان
307و308تغيير طريقة الطلب ويجبران المتصفح على إعادة إرسالPOSTللرابط الجديد! - أرسل التحويل القياسي بكتابة:
header("Location: /thank-you.php", true, 303); exit;.
يؤدي تمرير 303 كمعامل ثالث في دالة header() لضبط رمز الحالة على 303 See Other لضمان تحول الطلب التالي إلى GET.
<?php
header("Location: /orders/summary.php", true, 303);
echo "Active Redirect Status: " . http_response_code() . " See Other\n";
لأن التحويل يبدأ طلب GET جديداً ومستقلاً، تختفي متغيرات PHP المحلية الخاصة بطلب POST. لذا تُستخدم الرسائل المؤقتة (Flash Messages) لحفظ التنبيه في $_SESSION ثم مسحه فور قراءته لأول مرة.
- احفظ الرسالة قبل التحويل:
$_SESSION["flash"] = ["tone" => "success", "text" => "Saved!"];. - في طلب
GETالتالي، اقرأ الرسالة في متغير محلي ثم احذفها فوراً من الجلسة عبرunset($_SESSION["flash"]). - بفضل حذف المفتاح فور قراءته، لن تظهر الرسالة مرة أخرى إذا قام المستخدم بتحديث الصفحة لاحقاً.
يلتقط معامل الدمج الفارغ ?? الرسالة داخل المتغير المحلي $flash، بينما تمسحها unset() من الجلسة حتى لا تتكرر عند التحديث التالي.
<?php
session_start();
$_SESSION["flash"] = "Changes saved successfully!";
// On the redirected GET request, consume once and unset:
$flash = $_SESSION["flash"] ?? null;
unset($_SESSION["flash"]);
echo "1st Render : " . ($flash ?? "None") . "\n";
echo "2nd Refresh: " . ($_SESSION["flash"] ?? "None") . "\n";
يُطبّق نمط PRG أيضاً عند فشل التحقق من النموذج؛ حيث تُحفظ رسائل الخطأ والمدخلات السابقة غير الحساسة في $_SESSION ثم يُحوّل المستخدم لصفحة النموذج بـ 303 لإعادة ملء الحقول.
- ينزعج المستخدمون عندما يضيع كل ما كتبوه بسبب خطأ في حقل واحد؛ لذا احتفظ بالحقول الآمنة (مثل الاسم والبريد) داخل
$_SESSION["old"]. - قاعدة أمنية صارمة: لا تخزن أبداً كلمات المرور أو أرقام البطاقات البنكية داخل
$_SESSION["old"]! - رمّز دائماً القيم المسترجعة باستخدام
htmlspecialchars()عند طباعتها داخل خاصيةvalue="..."في HTML.
تتم قراءة ومسح كل من الأخطاء والمدخلات السابقة في طلب GET، مع ترميز الاسم بـ htmlspecialchars() لحمايته داخل خاصية الحقل.
<?php
session_start();
$_SESSION["errors"] = ["email" => "Please enter a valid email address."];
$_SESSION["old"] = ["name" => "Tariq & Co.", "email" => "invalid-email"];
$errors = $_SESSION["errors"] ?? [];
$old = $_SESSION["old"] ?? [];
unset($_SESSION["errors"], $_SESSION["old"]);
$safeName = htmlspecialchars($old["name"] ?? "", ENT_QUOTES, "UTF-8");
echo 'Input value="' . $safeName . '" | Error: ' . $errors["email"] . "\n";
يمثل الجمع بين نمط التحويل PRG ورسائل التنبيه المؤقتة والاحتفاظ بالمدخلات السابقة الأساس القياسي لمعالجة النماذج في جميع أطر عمل PHP الحديثة.
- استخدم نمط PRG مع كل طلب
POSTيغير حالة البيانات، سواء عند نجاح العملية أو عند فشل التحقق. - استخدم دائماً الرمز
303 See Otherمتبوعاً بـexit;للانتقال النظيف منPOSTإلىGET. - احذف رسائل التنبيه وأخطاء التحقق والمدخلات السابقة من
$_SESSIONفور سحبها لمتغيرات العرض.
تقوم الدالة المساعدة pullFlash($key) بجلب الرسالة من الجلسة وحذفها في خطوة واحدة لإبقاء قوالب العرض نظيفة.
| المرحلة | طريقة الطلب ورمز الحالة | العملية على الجلسة $_SESSION |
|---|---|---|
| 1. Valid Form Submit | POST -> 303 See Other | Set $_SESSION["flash_success"] |
| 2. Invalid Form Submit | POST -> 303 See Other | Set $_SESSION["errors"] & $_SESSION["old"] |
| 3. Redirected Page Load | GET -> 200 OK | Read & immediately unset() flash/errors/old |
| 4. User Presses F5 Refresh | GET -> 200 OK | Session keys already empty; safe reload |
<?php
session_start();
$_SESSION["flash"] = ["tone" => "success", "msg" => "Ticket #88 submitted."];
function pullFlash($key) {
$val = $_SESSION[$key] ?? null;
unset($_SESSION[$key]);
return $val;
}
$alert = pullFlash("flash");
echo "[" . strtoupper($alert["tone"]) . "] " . $alert["msg"] . "\n";
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
يمثل الجمع بين نمط التحويل PRG ورسائل التنبيه المؤقتة والاحتفاظ بالمدخلات السابقة الأساس القياسي لمعالجة النماذج في جميع أطر عمل PHP الحديثة. استخدم نمط PRG مع كل طلب POST يغير حالة البيانات، سواء عند نجاح العملية أو عند فشل التحقق. استخدم دائماً الرمز 303 See Other متبوعاً بـ exit; للانتقال النظيف من POST إلى GET. احذف رسائل التنبيه وأخطاء التحقق والمدخلات السابقة من $_SESSION فور سحبها لمتغيرات العرض.
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 PRG & Flash نمط PRG والتنبيهات
- امنع تكرار إرسال النماذج عند تحديث الصفحة عبر نمط PRG ورسائل الجلسة المؤقتة Flash Messages في PHP 8.
- للمراجعة
- 02 The Duplicate POST Resubmission Problem مشكلة إعادة إرسال النماذج عند تحديث الصفحة
- المفهوم الأساسي لقسم مشكلة إعادة إرسال النماذج عند تحديث الصفحة في لغة PHP الحديثة.
- للمراجعة
- 03 How Post Redirect Get PRG Works آلية عمل نمط التحويل PRG خطوة بخطوة
- الصياغة البرمجية والتطبيق العملي المباشر لقسم آلية عمل نمط التحويل PRG خطوة بخطوة.
- للمراجعة
- 04 Sending 303 See Other Redirects إرسال التحويل القياسي 303 See Other بعد POST
- قواعد التحقق وأفضل الممارسات القياسية الخاصة بقسم إرسال التحويل القياسي 303 See Other بعد POST.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات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 محلياً ونفّذ المثال البرمجي المشروح في قسم مشكلة إعادة إرسال النماذج عند تحديث الصفحة للتحقق من المخرجات.
-
بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم آلية عمل نمط التحويل PRG خطوة بخطوة وقارن مخرجات التنفيذ.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي8 أسئلة تنتظرك +
ما المشكلة الأساسية التي يحلها نمط التحويل بعد الإرسال Post/Redirect/Get (PRG)؟
يحول نمط PRG المتصفح إلى طلب GET بعد معالجة POST بحيث يصبح تحديث الصفحة آمناً تماماً.
أي رمز حالة HTTP مخصص قياسياً لتحويل المتصفح من طلب POST إلى صفحة عرض بطريقة GET؟
يأمر الرمز 303 المتصفح صراحةً بطلب الرابط الجديد باستخدام طريقة GET.
لماذا يجب تخزين رسائل التنبيه المؤقتة (Flash) في $_SESSION بدلاً من متغير عادي مثل $message عند استخدام PRG؟
كل طلب HTTP يعمل في نطاق مستقل، بينما تحفظ $_SESSION البيانات عبر التحويل.
ما الذي يميز رسالة التنبيه المؤقتة (Flash Message) عن بيانات الجلسة الدائمة مثل $_SESSION["user_id"]؟
حذف المفتاح فور قراءته يضمن ظهور التنبيه للمستخدم مرة واحدة فقط.
ماذا يحدث إذا عرضت $_SESSION["flash"] في صفحة GET ولكنك نسيت استدعاء unset($_SESSION["flash"])؟
بدون unset() تبقى الرسالة محفوظة في $_SESSION وتظهر في كل الطلبات التالية.
عند فشل التحقق من النموذج في نمط PRG، ما الحقول التي يمنع منعاً باتاً حفظها داخل $_SESSION["old"]؟
لا يجوز أبداً تخزين كلمات المرور أو بيانات الدفع في الجلسة أو إعادة طباعتها في HTML.
كيف يجب طباعة القيمة السابقة المحفوظة ($old["name"]) داخل خاصية <input value="..."> في HTML؟
عدم ترميز علامات الاقتباس والوسوم داخل value="..." يكسر عنصر HTML ويسبب ثغرة XSS.
لماذا يجب تجنب استخدام رمزي الحالة 307 أو 308 عند التحويل بعد إرسال نموذج POST في نمط PRG؟
يتطلب نمط PRG التحول من POST إلى GET عبر الرمز 303، بينما يبقي 307/308 الطلب كـ POST.