طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 132 · تقنيات تطوير الواجهات الخلفية
الدرس 4 · الوحدة 1: تطوير المنطق لمعالجة الطلبات

استقبال الطلبات: GET و POST

كيف يصل ما يكتبه المستخدم في النموذج إلى كود الخادم؟ ⏱ نحو 35 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تقرأ بيانات الطلب من $_GET و $_POST و $_SERVER.
  • تربط نموذج HTML بملف PHP عبر action و method و name.
  • تختار GET أو POST بحسب الوظيفة، وتعالج الحقول الغائبة بـ ?? و isset.
  • تحمي صفحتك من XSS بـ htmlspecialchars.

١من أين تأتي بيانات الطلب؟

الصفحة تصير مفيدة حين تتفاعل مع المستخدم: يكتب كلمة بحث، أو يملأ نموذج تسجيل. هذه البيانات تصل الخادم داخل الطلب، ويضعها PHP لك جاهزة في مصفوفات ترابطية خاصة اسمها المتغيرات العامة الفائقة Superglobals:

المصفوفةماذا فيها؟من أين؟
$_GETبيانات سلسلة الاستعلامالرابط بعد ؟ مثل ?q=قهوة&sort=price
$_POSTبيانات النموذج المرسل بـ POSTجسم الطلب
$_SERVERمعلومات عن الطلب والخادممثل REQUEST_METHOD و REQUEST_URI
$_COOKIE و $_SESSIONالكوكيز والجلسةالدرس 8

أرسلنا للملف نفسه طلبين. لاحظ كيف تغيّرت $_GET:

<?phpecho "<p>المصفوفة \$_GET:</p><pre>";print_r($_GET);echo "</pre>";echo "<p>اسم المنتج: " . ($_GET['product'] ?? 'لم يُرسل') . "</p>";

كل قيمة في $_GET و $_POST نص، حتى qty=2 وصلت "2". وإن احتجت عددًا فحوّله: $qty = (int) ($_GET['qty'] ?? 1);

٢نموذج بحث بـ GET

النموذج <form> من مقرر 131 يكتمل الآن: السمة action تحدد إلى أي ملف يُرسل، و method تحدد الطريقة. وكل حقل يُرسل باسمه في السمة name؛ فالحقل بلا name لا يُرسل أبدًا.

<!DOCTYPE html><html lang="ar" dir="rtl"><body>  <h2>ابحث في المتجر</h2>  <form action="search.php" method="get">    <input name="q" placeholder="اسم المنتج">    <select name="sort">      <option value="price">الأرخص أولًا</option>      <option value="name">حسب الاسم</option>    </select>    <button>بحث</button>  </form></body></html>

مع GET يبني المتصفح الرابط بنفسه من الحقول: search.php?q=قهوة&sort=price. لذلك تستطيع حفظ نتيجة البحث في المفضلة أو مشاركتها. جرّبه بيدك في المختبر: املأ النموذج واضغط «بحث»، ثم راقب شريط العنوان:

🧪 مختبر الخادماضغط ▶ تشغيل، واملأ النموذج داخل المتصفح المصغّر، ثم افتح «📜 السجل» لترى الطلب.

٣نموذج تسجيل بـ POST

حين يرسل المستخدم بيانات تُحفظ أو تغيّر شيئًا (تسجيل، دخول، طلب شراء) نستخدم method="post". البيانات تذهب في جسم الطلب لا في الرابط، ونقرؤها من $_POST:

<?php$name = $_POST['name'] ?? '';$course = $_POST['course'] ?? ''; echo "<h2>تم استلام طلب التسجيل</h2>";echo "<p>الاسم: $name</p>";echo "<p>الدورة: $course</p>";

افتح سطر الطلب في السجل: البيانات في الجسم بعد سطر فارغ، والرابط نفسه نظيف. والترويسة Content-Type تخبر الخادم بشكل البيانات.

GETPOST
أين البيانات؟في الرابطفي جسم الطلب
تظهر في السجل والمفضلة؟نعملا
الحجممحدود (بضعة آلاف حرف)كبير، ويقبل رفع الملفات
إعادة الإرسالآمنة: تحديث الصفحة يعيد الجلب فقطالمتصفح يحذّرك: «هل تريد إعادة الإرسال؟»
متى؟البحث، والتصفية، وفتح صفحة عنصرالتسجيل، والدخول، والإضافة، والتعديل

٤الحقل الذي لم يُرسل

لا تفترض أبدًا أن الحقل وصل: قد يفتح المستخدم الصفحة مباشرة، أو يرسل طلبًا ناقصًا عمدًا. قراءة مفتاح غير موجود تعطي تحذيرًا:

✗ خطأ
<?php$name = $_GET['name'];echo "مرحبًا يا $name";
✓ صواب
<?php$name = $_GET['name'] ?? 'زائر';echo "مرحبًا يا $name";

الطلب في المثالين بلا أي بيانات: GET /hello.php

ولك طريقتان: ?? لقيمة بديلة، أو isset() لتسأل «هل وصل؟» وتتصرف:

<?phpif (isset($_GET['id'])) {    $id = (int) $_GET['id'];    echo "تفاصيل المنتج رقم $id";} else {    echo "اختر منتجًا من القائمة";}

٥ملف واحد للعرض والمعالجة

نمط شائع جدًّا: الملف نفسه يعرض النموذج إن جاءه طلب GET، ويعالج البيانات إن جاءه POST. نعرف الطريقة من $_SERVER['REQUEST_METHOD']:

<?phpif ($_SERVER['REQUEST_METHOD'] === 'POST') {    $msg = $_POST['message'] ?? '';    echo "<p>✓ وصلتنا رسالتك (" . mb_strlen($msg) . " حرفًا). شكرًا لك!</p>";} else {?>    <form method="post">      <textarea name="message">السلام عليكم</textarea>      <button>أرسل</button>    </form><?php}

النموذج بلا action، فيُرسل إلى الصفحة نفسها. و mb_strlen تعدّ الحروف العربية صحيحًا (أما strlen فتعدّ البايتات).

٦لا تطبع ما يرسله المستخدم كما هو

ماذا لو كتب المستخدم في حقل الاسم كود HTML أو JavaScript بدل اسمه؟ إن طبعناه كما هو، سيُنفَّذ في صفحتنا! هذا هجوم مشهور اسمه XSS (حقن السكربت). شاهد الفرق:

✗ خطأ
<?php$name = $_GET['name'] ?? '';echo "<p>مرحبًا يا $name</p>";
✓ صواب
<?php$name = $_GET['name'] ?? '';echo "<p>مرحبًا يا " . htmlspecialchars($name) . "</p>";

الطلب في الحالتين: ?name=<b style="color:red…">مخترق</b>. في الخطأ صار نص المستخدم وسمًا حقيقيًّا. وفي الصواب حوّلت htmlspecialchars العلامة < إلى &lt; فظهرت نصًّا عاديًّا.

توقّع وتحقّق

حقل نموذج اسمه email أُرسل بـ POST. نقرؤه بـ:

المفتاح هو قيمة السمة name.

أي الطلبات يناسبه GET؟

البحث لا يغيّر شيئًا على الخادم.

ما فائدة htmlspecialchars؟

تحمي من XSS.

كيف يعرف الملف أن الطلب POST؟

قيمتها GET أو POST.

الخلاصة

تحدٍّ برمجي: حاسبة على الخادم

متوسط

اكتب الملف calc.php: إن جاءه طلب GET يعرض نموذج الحاسبة، وإن جاءه POST يحسب ويعرض النتيجة. الحساب يتم على الخادم.

المطلوب:
  • عند GET: اعرض نموذجًا method="post" فيه حقلان a و b، وقائمة op فيها + - * /.
  • عند POST: حوّل a و b إلى أعداد، واطبع <p>النتيجة: 9</p> (بالعدد الصحيح طبعًا).
  • إن كانت العملية قسمة و b صفرًا فاطبع <p>لا يمكن القسمة على صفر</p>.
  • يجب ألا يظهر أي تحذير في أي طلب.
👀 اعرض الاستجابة المطلوبة
✓ التحقق الآلي: يرسل المختبر هذه الطلبات إلى خادمك بالترتيب ثم يفحص الاستجابات
  1. GET /calc.php
  2. POST /calc.php (a=6&b=3&op=+)
  3. POST /calc.php (a=6&b=3&op=*)
  4. POST /calc.php (a=7&b=2&op=/)
  5. POST /calc.php (a=5&b=0&op=/)
  • الكود يعمل بلا أخطاء أو تحذيرات
  • GET يعرض نموذجًا method="post" فيه الحقول a و b و op
  • 6 + 3 ← النتيجة: 9
  • 6 * 3 ← النتيجة: 18
  • 7 / 2 ← النتيجة: 3.5
  • 5 / 0 ← لا يمكن القسمة على صفر
  • نتيجة POST لا تعرض النموذج مرة أخرى
  • تفحص طريقة الطلب بـ REQUEST_METHOD

💡 تلميح 1
ابدأ بـ if ($_SERVER['REQUEST_METHOD'] === 'POST') { … } else { …النموذج… } كما في القسم 5.
💡 تلميح 2
حوّل القيم بـ (float) حتى تعمل 3.5، واستخدم ?? حتى لا يظهر تحذير.
💡 تلميح 3
العلامة + في جسم الطلب تُرمَّز %2B، والمتصفح يفعل ذلك تلقائيًّا؛ فقط قارن $op === '+'.

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

<?phpif ($_SERVER['REQUEST_METHOD'] === 'POST') {    $a = (float) ($_POST['a'] ?? 0);    $b = (float) ($_POST['b'] ?? 0);    $op = $_POST['op'] ?? '+';     if ($op === '/' && $b == 0) {        echo "<p>لا يمكن القسمة على صفر</p>";    } else {        if ($op === '+') $r = $a + $b;        elseif ($op === '-') $r = $a - $b;        elseif ($op === '*') $r = $a * $b;        else $r = $a / $b;        echo "<p>النتيجة: $r</p>";    }} else {?><form method="post">  <input name="a"> <input name="b">  <select name="op">    <option>+</option><option>-</option><option>*</option><option>/</option>  </select>  <button>احسب</button></form><?php}
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس