تخطَّ إلى المحتوى

الجلسات والكوكيز في PHP: كيف يتذكر الموقع زائره

الدرس 10 من 12 · PHP

تسجّل دخولك في موقع، ثم تنتقل بين عشر صفحات وهو ما زال يعرف من أنت. تضيف منتجاً إلى السلة، فتجده فيها بعد ساعة. كيف يتذكرك الموقع؟ في هذا الدرس ستتعلم الأداتين اللتين يقوم عليهما ذلك: الكوكيز (Cookies) والجلسات (Sessions)، وستبني بهما نظام تسجيل دخول بسيطاً.

بروتوكول الويب HTTP بلا ذاكرة: كل طلب يصل إلى الخادم يُعامل كأنه من زائر جديد تماماً. تخيّل موظف استقبال يفقد ذاكرته كل دقيقة: في كل مرة تكلّمه يسألك «من أنت؟».

هناك حلان، وكلاهما يشبه شيئاً تعرفه:

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

الكوكيز: بيانات عند الزائر

Section titled “الكوكيز: بيانات عند الزائر”

الكوكي قيمة نصية صغيرة يحفظها المتصفح، ويرسلها تلقائياً مع كل طلب للموقع نفسه. ننشئها بالدالة setcookie، ونقرؤها من المصفوفة $_COOKIE:

visits.php
<?php
$visits = (int) ($_COOKIE["visits"] ?? 0);
$visits++;
setcookie("visits", (string) $visits, time() + 60 * 60 * 24 * 30);
echo "هذه زيارتك رقم $visits";

افتح الصفحة ثم حدّثها عدة مرات:

الناتج
هذه زيارتك رقم 1
هذه زيارتك رقم 2
هذه زيارتك رقم 3
  • في أول زيارة لا توجد كوكي بعد، فأعطى المعامل ?? القيمة صفر.
  • المعامل الثالث هو وقت الانتهاء: الوقت الحالي time() زائد عدد الثواني في ثلاثين يوماً. بدونه تُحذف الكوكي عند إغلاق المتصفح.
  • القيمة المقروءة نص دائماً، فحوّلناها بـ (int).

الكوكيز مناسبة للتفضيلات البسيطة: اللغة، والوضع الليلي، وآخر صفحة زارها المستخدم. لكنها غير آمنة للبيانات المهمة: الزائر يستطيع أن يراها ويعدّلها من أدوات المتصفح. لا تكتب فيها أبداً شيئاً مثل is_admin=1.

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

Section titled “الجلسات: بيانات عند الخادم”

في الجلسة تبقى البيانات على الخادم، ولا يصل إلى المتصفح إلا كوكي واحدة فيها رقم عشوائي طويل يسمى معرّف الجلسة. لا يستطيع الزائر أن يغيّر ما في خزانته.

استخدامها سهل: استدعِ session_start() في أول الصفحة، ثم تعامل مع $_SESSION كأي مصفوفة:

cart.php
<?php
session_start();
$_SESSION["cart"] ??= [];
if (isset($_GET["add"])) {
$_SESSION["cart"][] = $_GET["add"];
}
echo "في السلة: " . count($_SESSION["cart"]) . " منتجات";

افتح cart.php ثم cart.php?add=pen ثم cart.php?add=bag، وبعدها cart.php وحدها:

الناتج
في السلة: 0 منتجات
في السلة: 1 منتجات
في السلة: 2 منتجات
في السلة: 2 منتجات

السلة احتفظت بمحتواها بين الطلبات. والمعامل ??= ينشئ السلة فارغة في أول مرة فقط.

الكوكيز الجلسات
مكان التخزين متصفح الزائر الخادم
هل يستطيع الزائر تعديلها؟ نعم لا
مدة البقاء حتى التاريخ الذي تحدده حتى إغلاق المتصفح غالباً
مناسبة لـ التفضيلات البسيطة تسجيل الدخول والسلة

مشروع: تسجيل الدخول والخروج

Section titled “مشروع: تسجيل الدخول والخروج”

سنبني ثلاث صفحات. الأولى نموذج الدخول:

login.php
<?php
session_start();
$error = "";
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$username = trim($_POST["username"] ?? "");
$password = $_POST["password"] ?? "";
if ($username === "sara" && $password === "secret123") {
session_regenerate_id(true);
$_SESSION["user"] = $username;
header("Location: dashboard.php");
exit;
}
$error = "اسم المستخدم أو كلمة السر غير صحيحة";
}
?>
<form method="post">
<input name="username" placeholder="اسم المستخدم">
<input name="password" type="password" placeholder="كلمة السر">
<button>دخول</button>
</form>
<p><?= htmlspecialchars($error) ?></p>

إذا صحّت البيانات نحفظ اسم المستخدم في الجلسة، ثم نحوّله إلى الصفحة الخاصة بالدالة header، ونكتب بعدها exit حتى لا يكمل الكود تنفيذه. والدالة session_regenerate_id تغيّر معرّف الجلسة عند الدخول، وهذه حماية من نوع من الهجمات يسمى «تثبيت الجلسة».

الصفحة الثانية خاصة، لا يراها إلا من سجّل دخوله:

dashboard.php
<?php
session_start();
if (!isset($_SESSION["user"])) {
header("Location: login.php");
exit;
}
echo "أهلاً " . htmlspecialchars($_SESSION["user"]) . "! هذه صفحة خاصة.";

هذه الأسطر في أعلى الصفحة هي الحارس: من ليس في جلسته مستخدم يُعاد إلى صفحة الدخول. ضعها في كل صفحة تريد حمايتها.

والثالثة للخروج:

logout.php
<?php
session_start();
$_SESSION = [];
session_destroy();
header("Location: login.php");
exit;

عند التجربة: فتح dashboard.php مباشرة يعيدك إلى صفحة الدخول. وكلمة سر خاطئة تعرض رسالة الخطأ. والبيانات الصحيحة تعرض:

الناتج
أهلاً sara! هذه صفحة خاصة.

وبعد زيارة logout.php تعود dashboard.php مغلقة من جديد.

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

تلميح: الرابطان يكونان theme.php?set=dark و theme.php?set=light، واقبل هاتين القيمتين فقط.

  • نسيان session_start(): بدونها تكون $_SESSION مصفوفة عادية تُنسى بنهاية الصفحة. استدعها في أول كل صفحة تستخدم الجلسة.
  • مخرجات قبل الترويسات: أي echo أو حتى سطر فارغ قبل <?php يمنع setcookie و header و session_start من العمل.
  • نسيان exit بعد التحويل: header("Location: ...") لا توقف الكود، فيكمل تنفيذ الصفحة الخاصة ويرسلها!
  • الثقة في الكوكيز: أي قيمة في $_COOKIE كتبها المتصفح، وقد يكون الزائر عدّلها. عاملها مثل مدخلات النماذج.

سؤال

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

سؤال

لماذا نكتب exit بعد header('Location: login.php')؟

  • HTTP بلا ذاكرة، والكوكيز والجلسات تجعلان الموقع يتذكر زائره.
  • setcookie تحفظ قيمة عند الزائر، وتُقرأ من $_COOKIE، وهي للتفضيلات البسيطة.
  • session_start() ثم $_SESSION تحفظان البيانات على الخادم، وهي للبيانات المهمة.
  • حارس الصفحة: إذا لم يكن في الجلسة مستخدم، حوّله بـ header ثم exit.
  • كلمات السر تُحفظ بـ password_hash وتُفحص بـ password_verify.