$_SESSION

Ma Mariya Vinciya Updated 21 Oct 2026
7 min read ·Lesson 154 of 174
In this post

What Is a Session? In simple terms: A session lets a website remember information about a visitor across multiple pages — for example, that they are logged in, what is in their shopping cart, or a mes

What Is a Session?

In simple terms: A session lets a website remember information about a visitor across multiple pages — for example, that they are logged in, what is in their shopping cart, or a message to show after a redirect. The information is stored on the server, and the browser only keeps a random ID that identifies its session.

Technically: session_start() creates or resumes a session. PHP identifies the session through a cookie (named PHPSESSID by default) that contains a long random session ID. Session data is stored server-side (in files by default) and is available in the $_SESSION superglobal. At the end of the request, PHP writes any changes back to storage.

Sessions vs Cookies

CookiesSessions
Where data is storedIn the browserOn the server
What the browser holdsThe data itselfOnly a session ID
Can the user read or edit the data?YesNo
Size limitAbout 4 KBLimited only by server storage
LifetimeUntil the expiry dateUntil the session ends or expires on the server
Typical usePreferences, "remember me" tokensLogin state, carts, flash messages, CSRF tokens

 


Starting a Session and Using $_SESSION

Example: Visit Counter

<?php
// counter.php
session_start();

$_SESSION['visits'] = ($_SESSION['visits'] ?? 0) + 1;

echo "You have viewed this page {$_SESSION['visits']} time(s) in this session.";

 

Output on Three Consecutive Requests From the Same Browser

You have viewed this page 1 time(s) in this session.
You have viewed this page 2 time(s) in this session.
You have viewed this page 3 time(s) in this session.

 

What Happens Behind the Scenes

  1. First request: the browser has no session cookie. session_start() generates a new random ID, creates an empty session, and sends a Set-Cookie: PHPSESSID=... header.
  2. The script stores visits = 1 in $_SESSION; PHP saves it to the session storage when the script ends.
  3. Next requests: the browser sends the PHPSESSID cookie. session_start() loads the matching data into $_SESSION, so the counter continues.
  4. A different browser (or a private window) has a different session and starts again at 1.

Rules for session_start()

  • Call it before any output, because it may need to send a cookie header (otherwise: "Session cannot be started after headers have already been sent").
  • Call it on every page that reads or writes $_SESSION. Without it, $_SESSION is not loaded.
  • In larger applications, a front controller or bootstrap file calls it once for all pages.

Reading, Writing, and Removing Session Data

<?php
session_start();

// Write
$_SESSION['user_id'] = 42;
$_SESSION['cart'] = ['PEN-01' => 3, 'NB-A5' => 1];

// Read with defaults
$userId = $_SESSION['user_id'] ?? null;
$itemCount = array_sum($_SESSION['cart'] ?? []);

// Update nested data
$_SESSION['cart']['PEN-01'] += 2;

// Remove one value
unset($_SESSION['cart']['NB-A5']);

 

$_SESSION behaves like an ordinary array. Values can be strings, numbers, booleans, and arrays. Avoid storing objects that hold resources (database connections, file handles), because session data must be serialized to be saved.


Practical Example: Login and Logout

Logging In

<?php
// login.php
session_start();

function findUserByEmail(string $email): ?array
{
    // In a real application, this runs a database query.
    $users = [
        'asha@example.com' => [
            'id' => 7,
            'name' => 'Asha',
            'password_hash' => password_hash('Secure#2026', PASSWORD_DEFAULT),
        ],
    ];

    return $users[strtolower($email)] ?? null;
}

$error = null;

if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
    $email = is_string($_POST['email'] ?? null) ? trim($_POST['email']) : '';
    $password = is_string($_POST['password'] ?? null) ? $_POST['password'] : '';

    $user = findUserByEmail($email);

    if ($user !== null && password_verify($password, $user['password_hash'])) {
        session_regenerate_id(true);

        $_SESSION['user_id'] = $user['id'];
        $_SESSION['user_name'] = $user['name'];

        header('Location: /dashboard.php', true, 303);
        exit;
    }

    $error = 'Invalid email or password.';
}

 

Protecting a Page

<?php
// dashboard.php
session_start();

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

echo 'Welcome back, ' . htmlspecialchars($_SESSION['user_name']) . '!';

 

Logging Out

<?php
// logout.php (should be triggered by a POST request with a CSRF token)
session_start();

$_SESSION = [];

$params = session_get_cookie_params();
setcookie(session_name(), '', [
    'expires' => time() - 3600,
    'path' => $params['path'],
    'domain' => $params['domain'],
    'secure' => $params['secure'],
    'httponly' => $params['httponly'],
    'samesite' => $params['samesite'],
]);

session_destroy();

header('Location: /login.php', true, 303);
exit;

 

Step-by-Step Explanation

  1. Login verifies the password with password_verify() against a stored hash (see Password Hashing). The same error message is used for unknown emails and wrong passwords, so attackers cannot discover which emails are registered.
  2. session_regenerate_id(true) gives the session a new ID right after login and deletes the old session data file. This prevents session fixation, an attack where the attacker plants a known session ID in the victim's browser before they log in.
  3. Only the user's ID and display name are stored — never the password or its hash.
  4. Protected pages check for user_id and redirect visitors who are not logged in.
  5. Logout empties $_SESSION, deletes the session cookie (with the same parameters it was created with), and destroys the server-side data. Calling only session_destroy() would leave the data in $_SESSION for the rest of the request and the cookie in the browser.

Flash Messages

A flash message is stored in the session, shown once after a redirect, and then removed:

<?php
function flash(string $key, ?string $message = null): ?string
{
    if ($message !== null) {
        $_SESSION['_flash'][$key] = $message;
        return null;
    }

    $value = $_SESSION['_flash'][$key] ?? null;
    unset($_SESSION['_flash'][$key]);

    return $value;
}

// After saving a form:   flash('success', 'Profile updated.');  then redirect
// On the next page:      if ($msg = flash('success')) { echo htmlspecialchars($msg); }

 

This works together with the Post/Redirect/Get pattern described in \$_POST.


Secure Session Configuration

Configure the session cookie before calling session_start():

<?php
session_set_cookie_params([
    'lifetime' => 0,          // until the browser closes
    'path' => '/',
    'secure' => true,         // HTTPS only
    'httponly' => true,       // not readable by JavaScript
    'samesite' => 'Lax',
]);

ini_set('session.use_strict_mode', '1');   // reject unknown session IDs

session_start();

 

SettingWhy
secureThe session ID must never travel over plain HTTP
httponlyXSS cannot steal the session ID through document.cookie
samesite=LaxReduces CSRF risk
session.use_strict_mode=1PHP refuses to accept session IDs it did not create, which blocks a form of session fixation
session_regenerate_id(true) after login and privilege changesNew ID whenever the user's access level changes

 

These can also be set globally in php.ini (session.cookie_secure, session.cookie_httponly, session.cookie_samesite).


Session Lifetime and Storage

  • Expiry: Sessions expire after a period of inactivity determined by session.gc_maxlifetime (default 1440 seconds \= 24 minutes). PHP's garbage collector removes old session files probabilistically, so expiry is not exact. For a strict timeout, store a "last activity" timestamp in the session and check it on each request.
  • Storage: By default, sessions are stored as files on the server. Applications running on several servers use shared storage such as Redis, Memcached, or a database, so that any server can load any session.
  • Locking: With file storage, PHP locks the session for the duration of a request. A slow request blocks other requests from the same user (for example, parallel AJAX calls). Call session_write_close() as soon as you have finished writing session data in long-running scripts.
<?php
session_start();
$userId = $_SESSION['user_id'] ?? null;
session_write_close();   // release the lock; $_SESSION can still be read but changes are not saved

// ... long-running work, such as generating a report ...

 


Common Mistakes

Calling session_start() After Output

Effect: Warning, and the session cookie cannot be sent.

Fix: Start the session before any output.

Forgetting session_start() on a Page

Effect: $_SESSION is empty, so the user appears logged out.

Fix: Start the session on every page that uses it (preferably in a shared bootstrap file).

Not Regenerating the ID After Login

Effect: Session fixation attacks.

Fix: session_regenerate_id(true) immediately after successful login.

Storing Sensitive or Large Data

Effect: Passwords in session files, slow requests with huge sessions.

Fix: Store identifiers (user ID), not secrets; load other data from the database when needed.

Incomplete Logout

Effect: The session cookie or data remains.

Fix: Clear $_SESSION, delete the cookie, and call session_destroy().

Trusting Session Data Forever

Effect: Users keep permissions that were revoked in the database.

Fix: Re-check important permissions against the database, or invalidate sessions when roles change.


Best Practices

  • Start sessions early, in one central place, with secure cookie parameters.
  • Store minimal data — usually the user's ID — and look up the rest.
  • Regenerate the session ID on login and whenever privileges change.
  • Implement logout completely and protect it with POST and a CSRF token.
  • Use shared session storage (Redis or a database) when running multiple servers, and release session locks early in long requests.

Official reference: https\://www.php.net/manual/en/reserved.variables.session.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else User-defined Functions Slicing Strings PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention Garbage Collection Project: Simple Blog PHP What is OOP PHP Classes/Objects The $this Keyword Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning MySQL Database MySQL Connect MySQL Create DB MySQL Create Table MySQL Insert Data MySQL Get Last ID MySQL Insert Multiple MySQL Prepared MySQL Select Data MySQL Where Debugging PHP Project: Image Upload Gallery $_SESSION $_ENV PHP RegEx RegEx Patterns Heredoc and Nowdoc RegEx Modifiers preg_match preg_replace preg_split PHP RegEx Functions Nullable Types Mixed and Never Types Nullsafe Operator PHP Attributes PHP Fibers Readonly Classes Property Hooks (PHP 8.4) Asymmetric Visibility (PHP 8.4) Reflection API SPL Data Structures Composer
Ask about this post
AI Ask about this post

Ask questions about $_SESSION and get answers drawn from it.

Signed-in readers only.