Sessions and Cookies

Course 2 · Ch 5
Sessions and Cookies: Login Systems and Authentication Basics
Remembering a visitor across multiple page loads — and building a simple, real login flow

HTTP is "stateless" — by default, PHP has no memory of one request to the next; every page load is treated as a brand-new, unrelated visitor. Sessions and cookies are the two main tools that let a site remember who's logged in, what's in a shopping cart, or any other state that needs to persist across page loads.

Cookies — Small Bits of Data Stored in the Browser

<?php setcookie("username", "Philip", time() + 3600); // expires in 1 hour // On a LATER page load (after the browser sends the cookie back): echo $_COOKIE['username'] ?? 'Guest'; ?>
A cookie set with setcookie() is only available starting from the NEXT request
setcookie() must run before any HTML output begins (it sets an HTTP header), and the cookie won't appear in $_COOKIE until the browser sends it back on a subsequent page load — checking $_COOKIE['username'] immediately after setting it on the same page will not work as expected.

Sessions — Server-Side Storage, Linked by One Cookie

<?php session_start(); // MUST be the very first thing, before any output $_SESSION['username'] = "Philip"; $_SESSION['loggedIn'] = true; ?>
a later page, in a separate request
<?php session_start(); // must run on EVERY page that needs to read/write $_SESSION if ($_SESSION['loggedIn'] ?? false) { echo "Welcome back, " . $_SESSION['username']; } ?>

session_start() either creates a new session or resumes an existing one, identified by a single cookie PHP manages automatically (usually called PHPSESSID) — the actual data lives on the server, not in the browser, which is exactly why sessions are the right tool for anything sensitive, like login state.

Cookies

  • Stored in the visitor's browser
  • Visitor can view/edit/delete them directly
  • Good for: non-sensitive preferences (theme, language)

Sessions

  • Stored on the server; only an ID cookie sits in the browser
  • Visitor cannot read or tamper with the actual data
  • Good for: login state, anything sensitive

A Simple, Complete Login Flow

login.php
<?php session_start(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $username = $_POST['username'] ?? ''; $password = $_POST['password'] ?? ''; // Imagine $storedHash came from a database lookup by username (Chapter 4) $storedHash = password_hash("correct-password", PASSWORD_DEFAULT); // example only if (password_verify($password, $storedHash)) { $_SESSION['loggedIn'] = true; $_SESSION['username'] = $username; header("Location: dashboard.php"); exit; } else { $error = "Invalid username or password."; } } ?>
NEVER store or compare plain-text passwords
password_hash() turns a password into a scrambled, one-way string before it's ever stored — even if a database is somehow exposed, the original passwords cannot be recovered from the hashes. password_verify($plainPassword, $storedHash) checks a login attempt against that hash without ever needing to "decrypt" it back to plain text — because it genuinely cannot be reversed by design.

Protecting a Page — Requiring Login

dashboard.php
<?php session_start(); if (!($_SESSION['loggedIn'] ?? false)) { header("Location: login.php"); exit; // CRITICAL — stops the rest of the page from running } echo "Welcome to your dashboard, " . $_SESSION['username'] . "!"; ?>
header("Location: ...") without exit afterward is a common, serious mistake
header() sends a redirect instruction to the browser, but PHP itself keeps executing the rest of the script unless exit (or die()) is called immediately after — without it, a logged-out visitor could still see page content that was meant to be protected, briefly, before the redirect actually takes effect in their browser.

Logging Out

<?php session_start(); $_SESSION = []; // clear all session data session_destroy(); // destroy the session itself on the server header("Location: login.php"); exit; ?>

Coding Challenges

Challenge 1

Write a script that uses session_start() and checks if $_SESSION['visits'] exists — if not, set it to 1; if it does, increment it by 1. Echo "You have visited this page X times." Reload the same page (conceptually) and explain why the count keeps increasing.

📄 View solution
Challenge 2

Using password_hash() and password_verify(), write a script that hashes the password "MySecret123", then checks two test inputs — one matching, one not — against the hash, echoing whether each one would be allowed to log in.

📄 View solution
Challenge 3

Write a small "protected page" pattern: a function requireLogin() that checks $_SESSION['loggedIn'], redirecting to "login.php" with header() + exit if not set. Then write a logout script that clears the session and destroys it. Explain in a comment why exit is essential right after the header() redirect call.

📄 View solution

Chapter 5 Quick Reference

  • setcookie(name, value, expiry) — browser-stored, visitor-editable; for non-sensitive data only
  • session_start() — must run before ANY output, on every page using $_SESSION
  • $_SESSION[...] — server-side storage, linked by one cookie; safe for login state
  • password_hash() / password_verify() — never store or compare plain-text passwords
  • header("Location: ...") + exit — redirect; exit is essential to stop the rest of the script running
  • session_destroy() + clearing $_SESSION — the logout pattern
  • Next chapter: namespaces and autoloading — PSR-4, Composer basics