Kodokon kodokon.com

Sessions and cookies: login and shopping cart

Remember your visitors from page to page: secure login, a session-based shopping cart, and properly protected cookies.

10 min · 3 questions

Open this lesson in Kodokon

HTTP remembers nothing: each request arrives fresh, with no link to the previous one. Sessions solve this problem: session_start() associates the visitor with a unique identifier, transmitted in a cookie, and a storage space on the server side accessible via $_SESSION. Call session_start() right at the top of every relevant page, before any output.

PHP
<?php

declare(strict_types=1);

session_start();

$storedHash = password_hash('secret123', PASSWORD_DEFAULT);
$password = $_POST['password'] ?? '';

if (password_verify($password, $storedHash)) {
    session_regenerate_id(true);
    $_SESSION['user_id'] = 42;
    header('Location: /account.php');
    exit;
}

echo "Invalid credentials.";
login.php: in reality, the hash comes from your database.

Protecting a page comes down to checking the user's presence in the session, and redirecting otherwise. The session also serves as the ideal temporary storage for a shopping cart: an associative array product id => quantity survives from page to page.

PHP
<?php

declare(strict_types=1);

session_start();

if (!isset($_SESSION['user_id'])) {
    header('Location: /login.php');
    exit;
}

$_SESSION['cart'] ??= [];

$productId = filter_input(
    INPUT_POST,
    'product_id',
    FILTER_VALIDATE_INT
);

if (is_int($productId)) {
    $qty = $_SESSION['cart'][$productId] ?? 0;
    $_SESSION['cart'][$productId] = $qty + 1;
}

$count = array_sum($_SESSION['cart']);
echo "Cart: " . $count . " item(s)";
cart.php: a protected page and a cart stored in the session.

Cookies, on the other hand, live on the user's device and survive closing the browser: perfect for a theme or a language preference. Since PHP 7.3, setcookie() accepts an array of options: require secure (HTTPS only), httponly (invisible to JavaScript), and samesite (limits sending from other sites).

PHP
<?php

setcookie('theme', 'dark', [
    'expires' => time() + 60 * 60 * 24 * 30,
    'path' => '/',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);

$theme = $_COOKIE['theme'] ?? 'light';
echo "Active theme: " . $theme;
A preference cookie valid for thirty days, with the right flags.

Logging out must be as carefully done as logging in: empty $_SESSION, destroy the session on the server side, and expire the cookie that carried the identifier.

PHP
<?php

session_start();

$_SESSION = [];
session_destroy();

setcookie(session_name(), '', time() - 3600, '/');

header('Location: /login.php');
exit;
logout.php: a complete logout, leaving no trace.

Knowledge check

Make sure you remember the key points of this lesson.

  1. Where is a PHP session's data stored?
    • In a cookie on the user's device
    • On the server; the browser only keeps an identifier in a cookie
    • In the URL of each page
    • In the browser's localStorage
  2. Why call session_regenerate_id(true) right after a successful login?
    • To prevent session fixation: an identifier known before login becomes unusable
    • To extend the lifetime of the session cookie
    • To clear the old cart data
  3. What does a cookie's httponly option do?
    • It encrypts the cookie's contents
    • It restricts the cookie to insecure connections
    • It makes the cookie inaccessible to the page's JavaScript, which limits theft via XSS