استقبال الطلبات: 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>
<?php$q = $_GET['q'] ?? '';$sort = $_GET['sort'] ?? 'price'; echo "<p>تبحث عن: <b>$q</b></p>";echo "<p>الترتيب: $sort</p>";echo '<a href="form.html">بحث جديد</a>';
مع 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 تخبر الخادم بشكل البيانات.
| GET | POST | |
|---|---|---|
| أين البيانات؟ | في الرابط | في جسم الطلب |
| تظهر في السجل والمفضلة؟ | نعم | لا |
| الحجم | محدود (بضعة آلاف حرف) | كبير، ويقبل رفع الملفات |
| إعادة الإرسال | آمنة: تحديث الصفحة يعيد الجلب فقط | المتصفح يحذّرك: «هل تريد إعادة الإرسال؟» |
| متى؟ | البحث، والتصفية، وفتح صفحة عنصر | التسجيل، والدخول، والإضافة، والتعديل |
٤الحقل الذي لم يُرسل
لا تفترض أبدًا أن الحقل وصل: قد يفتح المستخدم الصفحة مباشرة، أو يرسل طلبًا ناقصًا عمدًا. قراءة مفتاح غير موجود تعطي تحذيرًا:
<?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 العلامة < إلى < فظهرت نصًّا عاديًّا.
توقّع وتحقّق
حقل نموذج اسمه email أُرسل بـ POST. نقرؤه بـ:
name.أي الطلبات يناسبه GET؟
ما فائدة htmlspecialchars؟
XSS.كيف يعرف الملف أن الطلب POST؟
GET أو POST.الخلاصة
- بيانات الطلب في مصفوفات ترابطية: $
_GETمن الرابط، و $_POSTمن جسم الطلب. - النموذج:
action= الملف،method= الطريقة، والحقل يُرسل باسمه فيname. - كل ما يصل نص؛ حوّله بـ
(int)أو(float)عند الحاجة. - لا تفترض وصول الحقل: ?? أو
isset(). - $
_SERVER['REQUEST_METHOD']يتيح لملف واحد أن يعرض ويعالج. - اطبع بيانات المستخدم دائمًا عبر
htmlspecialcharsلتمنعXSS.
تحدٍّ برمجي: حاسبة على الخادم
متوسطاكتب الملف calc.php: إن جاءه طلب GET يعرض نموذج الحاسبة، وإن جاءه POST يحسب ويعرض النتيجة. الحساب يتم على الخادم.
- عند GET: اعرض نموذجًا
method="post"فيه حقلانaوb، وقائمةopفيها+ - * /. - عند POST: حوّل a و b إلى أعداد، واطبع
<p>النتيجة: 9</p>(بالعدد الصحيح طبعًا). - إن كانت العملية قسمة و b صفرًا فاطبع
<p>لا يمكن القسمة على صفر</p>. - يجب ألا يظهر أي تحذير في أي طلب.
👀 اعرض الاستجابة المطلوبة
GET /calc.phpPOST /calc.php(a=6&b=3&op=+)POST /calc.php(a=6&b=3&op=*)POST /calc.php(a=7&b=2&op=/)POST /calc.php(a=5&b=0&op=/)
- الكود يعمل بلا أخطاء أو تحذيرات
- GET يعرض نموذجًا
method="post"فيه الحقول a و b و op 6 + 3← النتيجة: 96 * 3← النتيجة: 187 / 2← النتيجة: 3.55 / 0← لا يمكن القسمة على صفر- نتيجة POST لا تعرض النموذج مرة أخرى
- تفحص طريقة الطلب بـ REQUEST_METHOD
💡 تلميح 1
if ($_SERVER['REQUEST_METHOD'] === 'POST') { … } else { …النموذج… } كما في القسم 5.💡 تلميح 2
(float) حتى تعمل 3.5، واستخدم ?? حتى لا يظهر تحذير.💡 تلميح 3
$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}