21. PHP Sessions and Cookies

What you will learn

  • Why websites need to remember visitors
  • How cookies and sessions differ
  • How to start a session and store data
  • How to build a simple login-style flow safely

The problem: HTTP forgets

Every page request is separate. The server does not remember that the same visitor loaded the last page. To keep a shopping basket or a login, the site must give the browser something to carry from page to page.

Cookies

A cookie is a small piece of text stored in the visitor’s browser. The browser sends it back with every request to your site.

PHP code: set-cookie.php

<?php
setcookie("theme", "dark", [
    "expires"  => time() + 60 * 60 * 24 * 30,   // 30 days
    "path"     => "/",
    "secure"   => false,     // set to true on a live HTTPS site
    "httponly" => true,
    "samesite" => "Lax",
]);

echo "Cookie sent. Open read-cookie.php next.";

PHP code: read-cookie.php

<?php
$theme = $_COOKIE["theme"] ?? "light";

echo "Your theme is: " . htmlspecialchars($theme, ENT_QUOTES, "UTF-8");

Output on read-cookie.php after visiting set-cookie.php first

Your theme is: dark

  • setcookie() must run before any output.
  • A cookie set on one request appears in $_COOKIE only from the next request.
  • httponly hides the cookie from JavaScript, and secure sends it only over HTTPS. samesite limits sending it from other sites.
  • To delete a cookie, set it again with an expires time in the past.

Cookies are controlled by the visitor. They can read, change, or delete them. Never trust a cookie, and never store passwords or private data in one. Cookies that are not strictly necessary may need visitor consent under privacy laws such as the GDPR, so check the rules for your audience.

Sessions

A session keeps data on the server. The browser holds only a random session ID in a cookie. PHP uses the ID to find the right data. This is why sessions are the right place for logins and baskets.

PHP code: visits.php

<?php
session_start();

if (!isset($_SESSION["visits"])) {
    $_SESSION["visits"] = 0;
}
$_SESSION["visits"]++;

echo "You have loaded this page " . $_SESSION["visits"] . " time(s) in this session.";

Output after loading the page three times

You have loaded this page 3 time(s) in this session.

  • Call session_start() at the very top, before any output, on every page that uses the session.
  • Store data in $_SESSION, which works like any associative array.

Cookie or session?

Cookie Session
Stored In the browser On the server (the browser keeps an ID)
Visitor can edit it Yes No, only the ID
Size Small (about 4 KB) Much larger
Lasts As long as you set Until the browser closes or it expires
Use for Harmless preferences such as a theme Logins, baskets, form tokens

A simple login flow

This example shows the idea with a fixed user so you can see the moving parts. A real site stores users in a database and checks passwords with password_verify(), as the next lessons explain.

PHP code: login.php

<?php
session_start();

$error = "";

if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $user = trim($_POST["username"] ?? "");
    $pass = $_POST["password"] ?? "";

    // Demo only: a real site checks a stored password HASH
    $demo_hash = password_hash("secret123", PASSWORD_DEFAULT);

    if ($user === "sam" && password_verify($pass, $demo_hash)) {
        session_regenerate_id(true);       // new ID after login
        $_SESSION["user"] = "sam";
        header("Location: dashboard.php");
        exit;
    }

    $error = "Wrong username or password.";
}
?>
<form method="post">
  <label for="u">Username</label>
  <input type="text" id="u" name="username">
  <label for="p">Password</label>
  <input type="password" id="p" name="password">
  <button type="submit">Log in</button>
</form>
<p><?= htmlspecialchars($error, ENT_QUOTES, "UTF-8") ?></p>

PHP code: dashboard.php

<?php
session_start();

if (!isset($_SESSION["user"])) {
    header("Location: login.php");
    exit;
}

echo "Welcome, " . htmlspecialchars($_SESSION["user"], ENT_QUOTES, "UTF-8") . "! ";
echo '<a href="logout.php">Log out</a>';

PHP code: logout.php

<?php
session_start();

$_SESSION = [];
if (ini_get("session.use_cookies")) {
    $p = session_get_cookie_params();
    setcookie(session_name(), "", time() - 3600, $p["path"], $p["domain"], $p["secure"], $p["httponly"]);
}
session_destroy();

header("Location: login.php");
exit;

What happens

Wrong password: the login page shows “Wrong username or password.”

Username sam and password secret123: the browser moves to the dashboard, which says “Welcome, sam!”

Visiting the dashboard without logging in sends you to the login page. Logging out clears the session.

Session security habits

  • Call session_regenerate_id(true) right after a successful login, to stop session fixation.
  • Protect every private page by checking $_SESSION at the top, then exit after the redirect.
  • Use HTTPS on a live site, and mark session cookies secure and httponly.
  • Never put the session ID in a web address.
  • Store as little as possible in a session, and never store a plain password.
  • Offer a logout that destroys the session fully.

WordPress handles logins for you with its own, carefully tested system. Do not build a login for WordPress by hand. Use its built-in accounts, roles, and plugins.

Common mistakes

  • Output before session_start() or setcookie(), giving “headers already sent”.
  • Forgetting session_start() on one of the pages.
  • Expecting a new cookie to be readable in the same request.
  • Trusting cookie values.
  • Forgetting exit after a redirect, so the page keeps running.
  • Not regenerating the session ID after login.

Exercise

Write a page that uses a session to remember a visitor’s chosen colour. If ?color=blue is in the address, save it (only if it is red, green, or blue). Always print Your colour is: followed by the saved value, or none.

Show solution
<?php
session_start();

$allowed = ["red", "green", "blue"];
$color = $_GET["color"] ?? "";

if (in_array($color, $allowed, true)) {
    $_SESSION["color"] = $color;
}

echo "Your colour is: " . htmlspecialchars($_SESSION["color"] ?? "none", ENT_QUOTES, "UTF-8");

Visit it with ?color=blue, then again with no query. It should still say blue.

Knowledge check

1. Where is a cookie stored, and where is session data stored?

Cookies are stored in the browser. Session data is stored on the server.

2. Which function must run first on every page that uses a session?

session_start()

3. Why call session_regenerate_id(true) after login?

To prevent session fixation, where an attacker plants a known session ID.

Summary

  • Cookies live in the browser and can be edited, so use them only for harmless preferences.
  • Sessions keep data on the server, and the browser holds only an ID.
  • Start sessions before output, regenerate the ID on login, protect private pages, and log out properly.
Scroll to Top