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

الكوكيز والجلسات

HTTP ينسى كل طلب؛ فكيف تبقى السلة ممتلئة وتبقى مسجّلًا؟ ⏱ نحو 35 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تشرح لماذا HTTP عديم الحالة وكيف تحل الكوكيز ذلك.
  • تنشئ الكوكيز وتقرؤها وتحذفها، وتعرف حدودها الأمنية.
  • تستخدم الجلسات لحفظ بيانات المستخدم على الخادم.
  • تميّز متى تستخدم الكوكي ومتى الجلسة، وتعرف إعدادات الأمان.

١HTTP بلا ذاكرة

كل طلب HTTP مستقل تمامًا: الخادم لا يتذكر أنك طلبت صفحة قبل ثانية. نقول إن HTTP بروتوكول عديم الحالة Stateless. فكيف يعرف المتجر ما في سلّتك؟ وكيف يبقى المستخدم مسجّلًا دخوله وهو يتنقل بين الصفحات؟

الحل فكرة بسيطة: الخادم يعطي المتصفح «بطاقة» صغيرة، والمتصفح يعيدها مع كل طلب تالٍ. هذه البطاقة اسمها الكوكي Cookie.

جرّب الملف التالي: عدّاد زيارات بسيط. أرسلنا له ثلاثة طلبات متتالية:

<?php$n = (int) ($_COOKIE['visits'] ?? 0) + 1;setcookie('visits', $n, time() + 30 * 24 * 3600);   // صالح 30 يومًاecho "<p>هذه زيارتك رقم $n</p>";

افتح السطر الأول: الاستجابة فيها Set-Cookie. ثم افتح الثاني: الطلب صار فيه الترويسة Cookie: visits=1 ، أي أن المتصفح أعاد البطاقة.

٢كيف تعمل الكوكيز؟

  1. الخادم يرسل في الاستجابة: Set-Cookie: visits=1; expires=…
  2. المتصفح يحفظها مرتبطة باسم الموقع.
  3. مع كل طلب تالٍ لنفس الموقع يرسل: Cookie: visits=1
  4. PHP يضعها لك في المصفوفة $_COOKIE.
ما تكتبه في PHPمعناه
setcookie('theme', 'dark', time() + 3600);أنشئ كوكي تنتهي بعد ساعة (3600 ثانية).
setcookie('theme', 'dark');كوكي جلسة: تُحذف عند إغلاق المتصفح.
$_COOKIE['theme'] ?? 'light'اقرأها، مع قيمة بديلة إن لم توجد.
setcookie('theme', '', time() - 3600);احذفها: تاريخ انتهاء في الماضي.
🧪 مختبر الخادماختر «داكن»، ثم اضغط «تحديث بلا معامل»: الخادم تذكّر اختيارك من الكوكي. ثم احذفها من تبويب الكوكيز وحدّث.

٣الجلسات: البيانات على الخادم

بما أن الكوكي غير موثوقة، نحفظ البيانات المهمة على الخادم، ونعطي المتصفح كوكي واحدة فقط فيها رقم عشوائي طويل يدل على بياناته. هذه هي الجلسة Session:

الكوكيالجلسة
أين البيانات؟في متصفح المستخدمعلى الخادم (ملفات في مجلد مؤقت)
ماذا يرى المستخدم؟البيانات نفسهارقم الجلسة فقط: PHPSESSID=8f2c…
هل يستطيع تغييرها؟نعملا (إلا إن سرق رقم جلسة غيره)
مناسبة لـتفضيلات غير حساسة: المظهر واللغةتسجيل الدخول، والسلة، والصلاحيات

وفي PHP ثلاث خطوات فقط: session_start() في أعلى كل ملف يستخدم الجلسة، ثم اقرأ واكتب في المصفوفة $_SESSION كأي مصفوفة:

<?phpsession_start();$products = ['coffee' => 'قهوة عربية', 'dates' => 'تمر سكري', 'tea' => 'شاي أخضر']; // إضافة إلى السلةif (isset($_GET['add'], $products[$_GET['add']])) {    $id = $_GET['add'];    $_SESSION['cart'][$id] = ($_SESSION['cart'][$id] ?? 0) + 1;}$cart = $_SESSION['cart'] ?? [];?><h3>المنتجات</h3><?php foreach ($products as $id => $name): ?>  <p><?= $name ?> — <a href="shop.php?add=<?= $id ?>">أضف للسلة</a></p><?php endforeach; ?><h3>سلتك (<?= array_sum($cart) ?>)</h3><ul><?php foreach ($cart as $id => $qty): ?>  <li><?= $products[$id] ?> × <?= $qty ?></li><?php endforeach; ?></ul><a href="clear.php">إفراغ السلة</a>

أول طلب أنشأ الجلسة (Set-Cookie: PHPSESSID). بعده يرسل المتصفح الرقم نفسه، فيجد PHP سلة هذا المستخدم. و clear.php أفرغت السلة ثم حوّلت إلى shop.php.

🧪 مختبر الخادمأضف منتجات وراقب السلة. ثم احذف كوكي PHPSESSID من تبويب الكوكيز وحدّث: ستبدو السلة فارغة، لأن الخادم لم يعد يعرف من أنت.

٤إنهاء الجلسة

<?phpsession_start(); unset($_SESSION['cart']);   // احذف مفتاحًا واحدًا $_SESSION = [];             // أفرغ كل بيانات الجلسةsession_destroy();          // واحذف ملفها من الخادم (عند تسجيل الخروج)

وستستخدم هذا كله في الدرس 16 لبناء تسجيل الدخول والخروج.

٥أمان الكوكيز والجلسات

رقم الجلسة يساوي «مفتاح الحساب» مؤقتًا: من سرقه دخل باسم صاحبه. لذلك:

الإعدادماذا يفعل؟
HttpOnlyتمنع JavaScript من قراءة الكوكي، فلا يسرقها سكربت XSS.
Secureلا تُرسل إلا عبر HTTPS المشفّر.
SameSite=Laxلا تُرسل مع طلبات تأتي من مواقع أخرى (حماية من هجوم CSRF).
<?php// قبل session_start: إعدادات آمنة لكوكي الجلسةsession_set_cookie_params([    'lifetime' => 0,          // تنتهي بإغلاق المتصفح    'httponly' => true,    'secure'   => true,       // على موقع HTTPS فقط    'samesite' => 'Lax',]);session_start(); // وبعد تسجيل الدخول الناجح: رقم جلسة جديدsession_regenerate_id(true);

توقّع وتحقّق

لماذا نحتاج الكوكيز والجلسات؟

HTTP عديم الحالة.

أين تُحفظ بيانات $_SESSION؟

والمتصفح يحمل رقمها فقط.

أي معلومة مناسبة لكوكي عادية؟

معلومة غير حساسة.

كيف تحذف كوكي؟

المتصفح يحذفها حين تنتهي.

الخلاصة

تحدٍّ برمجي: قائمة المفضلة في الجلسة

متوسط

اكتب fav.php لقائمة الدورات المفضلة لكل متدرب، تُحفظ في الجلسة.

المطلوب:
  • ?add=اسم يضيف الدورة إلى المفضلة (بلا تكرار: إن وُجدت لا تُضاف ثانية).
  • ?clear=1 يفرغ المفضلة.
  • في كل طلب اطبع العدد بالشكل <p>المفضلة: 2</p> ثم قائمة <ul> فيها كل دورة في <li> بترتيب الإضافة.
  • احفظ القائمة في $_SESSION['favs']، لا في كوكي.
👀 اعرض الاستجابة المطلوبة
✓ التحقق الآلي: يرسل المختبر هذه الطلبات إلى خادمك بالترتيب ثم يفحص الاستجابات
  1. GET /fav.php?add=PHP
  2. GET /fav.php?add=SQL
  3. GET /fav.php?add=PHP
  4. GET /fav.php
  5. GET /fav.php?clear=1
  • الكود يعمل بلا أخطاء أو تحذيرات
  • الخادم أنشأ جلسة (كوكي PHPSESSID)
  • بعد إضافتين: المفضلة: 2
  • إضافة PHP مرة ثانية لا تكررها
  • طلب بلا معاملات يعرض القائمة كما هي بالترتيب
  • clear يفرغ القائمة
  • تستخدم $_SESSION
  • لا تستخدم setcookie

💡 تلميح 1
ابدأ بـ session_start(); ثم $_SESSION['favs'] = $_SESSION['favs'] ?? [];
💡 تلميح 2
لمنع التكرار: !in_array($_GET['add'], $_SESSION['favs'])

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

<?phpsession_start();$_SESSION['favs'] = $_SESSION['favs'] ?? []; if (isset($_GET['clear'])) {    $_SESSION['favs'] = [];}if (isset($_GET['add']) && !in_array($_GET['add'], $_SESSION['favs'])) {    $_SESSION['favs'][] = $_GET['add'];} echo "<p>المفضلة: " . count($_SESSION['favs']) . "</p>";echo "<ul>";foreach ($_SESSION['favs'] as $f) {    echo "<li>" . htmlspecialchars($f) . "</li>";}echo "</ul>";
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

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