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

نمط التحويل بعد الإرسال PRG ورسائل التنبيه المؤقتة في PHPPHP Post Redirect Get Pattern and Flash Messages

امنع تكرار إرسال النماذج عند تحديث الصفحة عبر نمط PRG ورسائل الجلسة المؤقتة Flash Messages في PHP 8.
أقسام الدرس
6
الأمثلة
6
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
0
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع

عندما يعالج سكريبت PHP طلب POST ويطبع صفحة HTML مباشرة في نفس الاستجابة، يبقى آخر طلب مسجل في ذاكرة المتصفح هو طلب POST نفسه.

  • إذا ضغط المستخدم على زر تحديث الصفحة ، يعيد المتصفح إرسال نفس بيانات POST مرة ثانية للخادم.
  • في المتاجر الإلكترونية وأنظمة الحجز، يؤدي تكرار إرسال POST إلى خصم المبلغ مرتين أو إدراج سجلات مكررة في قاعدة البيانات.
  • القاعدة الذهبية: لا تعرض صفحة HTML النهائية مباشرة كرد على طلب POST أبداً!

نظراً لعدم إجراء تحويل بعد معالجة طلب POST، فإن تحديث الصفحة يعيد تنفيذ كود الإضافة ويكرر الطلب.

مخطط توضيحي: محاكي نمط التحويل بعد الإرسال (PRG) ورسائل التنبيه المؤقتة (Flash) في PHP
PHP
<?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
<?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
<?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
PHP
<?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
<?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 SubmitPOST -> 303 See OtherSet $_SESSION["flash_success"]
2. Invalid Form SubmitPOST -> 303 See OtherSet $_SESSION["errors"] & $_SESSION["old"]
3. Redirected Page LoadGET -> 200 OKRead & immediately unset() flash/errors/old
4. User Presses F5 RefreshGET -> 200 OKSession keys already empty; safe reload

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

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

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

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

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 محلياً ونفّذ المثال البرمجي المشروح في قسم مشكلة إعادة إرسال النماذج عند تحديث الصفحة للتحقق من المخرجات.

  2. بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم آلية عمل نمط التحويل PRG خطوة بخطوة وقارن مخرجات التنفيذ.

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

مساحة التحدي

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

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

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

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

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

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

ما المشكلة الأساسية التي يحلها نمط التحويل بعد الإرسال Post/Redirect/Get (PRG)؟

يحول نمط PRG المتصفح إلى طلب GET بعد معالجة POST بحيث يصبح تحديث الصفحة آمناً تماماً.

02

أي رمز حالة HTTP مخصص قياسياً لتحويل المتصفح من طلب POST إلى صفحة عرض بطريقة GET؟

يأمر الرمز 303 المتصفح صراحةً بطلب الرابط الجديد باستخدام طريقة GET.

03

لماذا يجب تخزين رسائل التنبيه المؤقتة (Flash) في $_SESSION بدلاً من متغير عادي مثل $message عند استخدام PRG؟

كل طلب HTTP يعمل في نطاق مستقل، بينما تحفظ $_SESSION البيانات عبر التحويل.

04

ما الذي يميز رسالة التنبيه المؤقتة (Flash Message) عن بيانات الجلسة الدائمة مثل $_SESSION["user_id"]؟

حذف المفتاح فور قراءته يضمن ظهور التنبيه للمستخدم مرة واحدة فقط.

05

ماذا يحدث إذا عرضت $_SESSION["flash"] في صفحة GET ولكنك نسيت استدعاء unset($_SESSION["flash"])؟

بدون unset() تبقى الرسالة محفوظة في $_SESSION وتظهر في كل الطلبات التالية.

06

عند فشل التحقق من النموذج في نمط PRG، ما الحقول التي يمنع منعاً باتاً حفظها داخل $_SESSION["old"]؟

لا يجوز أبداً تخزين كلمات المرور أو بيانات الدفع في الجلسة أو إعادة طباعتها في HTML.

07

كيف يجب طباعة القيمة السابقة المحفوظة ($old["name"]) داخل خاصية <input value="..."> في HTML؟

عدم ترميز علامات الاقتباس والوسوم داخل value="..." يكسر عنصر HTML ويسبب ثغرة XSS.

08

لماذا يجب تجنب استخدام رمزي الحالة 307 أو 308 عند التحويل بعد إرسال نموذج POST في نمط PRG؟

يتطلب نمط PRG التحول من POST إلى GET عبر الرمز 303، بينما يبقي 307/308 الطلب كـ POST.