Session Management
How sessions work and why they must start before any output
The Memory Box for Users
HTTP is "stateless" - each request is independent. Without sessions, the server forgets you between requests.
A session is how the server remembers small data about you:
- "This user is logged in"
- "This user has items in their cart"
- "This form had validation errors"
How Sessions Work
- First visit: Server creates a unique session ID (random string)
- Cookie sent: Server sends this ID to your browser as a cookie
- Browser stores: Your browser saves the cookie
- Next request: Browser sends the cookie back with every request
- Server remembers: Server uses the ID to load your session data
Think of it like a coat check:
- You give your coat (data) to the attendant (server)
- They give you a ticket (session ID cookie)
- You show the ticket on your next visit
- They return your coat (session data)
Session Name: Avoiding Collisions
$sessionName = 'daltphp_' . substr(sha1(BASE_PATH), 0, 8);
session_name($sessionName);
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
'httponly' => true,
'samesite' => 'Lax',
]);
session_start();Why a Custom Session Name?
By default, PHP uses PHPSESSID as the session cookie name. But what if you run two PHP apps on localhost?
The Problem:
App 1: localhost:8000 → uses PHPSESSID
App 2: localhost:8001 → uses PHPSESSIDBoth apps share the same cookie name on the same domain. They can:
- Overwrite each other's sessions
- Cause confusing login/logout behavior
- Mix up user data
The Solution:
$sessionName = 'daltphp_' . substr(sha1(BASE_PATH), 0, 8);
// Result: 'daltphp_a7f3c2e1'This creates a unique session name based on your project path:
- Different projects get different session names
- No more collisions on localhost
- Each app has its own "coat check counter"
Breaking Down the Code
sha1(BASE_PATH)
- Creates a hash of your project path
- Example:
/home/user/project1→a7f3c2e1b9d4...
substr(..., 0, 8)
- Takes first 8 characters of the hash
- Keeps the name short but unique enough
'daltphp_' . ...
- Adds a readable prefix
- Final result:
daltphp_a7f3c2e1
Starting the Session
session_name($sessionName);
session_start();The Critical Order
You must call session_name() before session_start(). Here's why:
What session_name() does:
- Sets the name of the session cookie
- Must be called before any session operations
What session_start() does:
- Reads the session cookie from the browser
- Loads session data from the server
- Fills the
$_SESSIONarray - Sends session cookie headers if needed
The Headers Problem
Sessions use HTTP cookies, which are sent in headers. In HTTP:
HTTP/1.1 200 OK
Set-Cookie: daltphp_a7f3c2e1=abc123xyz... ← Headers
Content-Type: text/html ← Headers
← Blank line
<html> ← Body starts hereThe Rule: Headers must be sent before the body.
If you output anything before session_start():
echo "Hello"; // ← Output sent (body starts)
session_start(); // ← ERROR! Can't send headers nowYou'll get:
Warning: session_start(): Cannot send session cookie -
headers already sent by (output started at ...)Why This File is Safe
In public/index.php:
- No
echo,print, or HTML beforesession_start() - No whitespace before
<?php - No included files that output content
This is intentional and important.
What Gets Stored in Sessions
After session_start(), you can use $_SESSION:
// Store data
$_SESSION['user'] = ['email' => 'user@example.com'];
$_SESSION['cart'] = ['item1', 'item2'];
// Read data
if (isset($_SESSION['user'])) {
echo "Welcome back!";
}
// Delete data
unset($_SESSION['cart']);Session Data Lives on the Server
Important: The cookie only stores the session ID, not the actual data.
In the browser cookie:
daltphp_a7f3c2e1=abc123xyz789On the server (in session files):
/tmp/sess_abc123xyz789
user|a:1:{s:5:"email";s:16:"user@example.com";}This is more secure than storing everything in cookies:
- Cookies are limited to ~4KB
- Cookies are sent with every request (bandwidth)
- Cookies can be read/modified by the user (security risk)
Session Lifecycle in DALT.PHP
1. Session Starts (Entry Point)
// public/index.php
session_start();2. Session Used (Throughout Request)
// Login controller
$_SESSION['user'] = ['email' => $email];
// Auth middleware
if (!isset($_SESSION['user'])) {
redirect('/login');
}
// View
echo "Hello, " . $_SESSION['user']['email'];3. Flash Data Added (On Errors)
// Validation exception handler
Session::flash('errors', $errors);
Session::flash('old', $oldInput);4. Flash Data Cleaned (End of Request)
// public/index.php (last line)
Session::unflash();Key Takeaways
- Sessions remember users - Essential for login, carts, flash messages
- Custom session names prevent collisions - Multiple local apps won't interfere
- Headers must come first - No output before
session_start() - Session ID in cookie, data on server - More secure than client-side storage
- Security is configured explicitly - HttpOnly, Secure, and SameSite protect against attacks
What's Good Here
✅ Unique session name per project (smart collision prevention)
✅ Session starts early, before any output
✅ Uses PHP's built-in session handling (battle-tested)
✅ Session data is server-side (more secure)
✅ Secure cookie parameters configured (HttpOnly, SameSite, Secure)
✅ Auto-detects HTTPS for secure flag
✅ Session cookie expires when browser closes (lifetime = 0)
Next, we'll look at how the framework bootstraps itself and loads the database.