PHP: Sessions and Login System

Cookies keep data in the user's browser; Sessions keep it on the server. Login state, shopping carts, permission flags — any data you don't want the user touching belongs in a session. By the end of this lesson, you'll have built your first login system.

1. What Is a Session?

A session is a private storage area on the server created for each user. The browser only holds a cookie with the Session ID; all the real data stays server-side:

TEXT 📖 Display only
Cookie:                          Session:
Only holds the Session ID        Stores the actual data (username, role, cart...)
┌──────────────┐                ┌──────────────────────┐
│ PHPSESSID    │  ──match──→   │ user: John            │
│ abc123       │                │ login: true           │
└──────────────┘                │ cart: [3 items]       │
   In the browser               │ role: admin           │
                                └──────────────────────┘
                                     On the server
💡 Tip: Session vs Cookie: Cookies live in the browser (visible and modifiable by the user); sessions live on the server (secure). But sessions rely on cookies to transmit the Session ID — if the user blocks cookies, sessions break.


2. session_start() — Starting a Session

You must call session_start() before using any session functionality. It does two things:

  1. If the browser sends a Session ID cookie → load the corresponding server data
  2. If no cookie is found → create a new session, generate a new ID, and send a cookie
PHP
<?php
// session_start() must come before any HTML output
session_start();

// Store data
$_SESSION['username'] = "John";
$_SESSION['login_time'] = date("Y-m-d H:i:s");

// Read data
echo "Welcome, {$_SESSION['username']}!";
echo "Logged in at: {$_SESSION['login_time']}";
?>
🔥 Common Mistake: session_start() must be called before any output — echo, raw HTML, even a stray space before the <?php tag. Otherwise you'll get the dreaded headers already sent error. Put it at the very top of your file.


3. $_SESSION — Use It Like Any Array

PHP
<?php
session_start();

// Store any PHP data type
$_SESSION['user'] = [
    'id'   => 101,
    'name' => 'John',
    'role' => 'member'
];
$_SESSION['cart'] = [
    ['name' => 'PHP Tutorial', 'price' => 39.90, 'qty' => 2],
    ['name' => 'MySQL Basics', 'price' => 29.90, 'qty' => 1],
];

// Read
echo $_SESSION['user']['name'];  // John

// Remove a single session variable
unset($_SESSION['cart']);

// Update
$_SESSION['user']['role'] = 'admin';
?>

▶ Example: A Session-Powered Shopping Cart

Output:

TEXT 📖 Display only
<h3>Your Cart</h3>
{item1} × {1}<br>
PHP
<?php
session_start();

// Initialize the cart
if (!isset($_SESSION['cart'])) {
    $_SESSION['cart'] = [];
}

// Add an item
if (isset($_POST['add'])) {
    $item = $_POST['add'];
    $_SESSION['cart'][$item] = ($_SESSION['cart'][$item] ?? 0) + 1;
}

echo "<h3>Your Cart</h3>";
foreach ($_SESSION['cart'] as $item => $qty) {
    echo "{$item} × {$qty}<br>";
}
?>
<form method='POST'>
    <button name='add' value='PHP Tutorial'>Add PHP Tutorial</button>
    <button name='add' value='MySQL Basics'>Add MySQL Basics</button>
</form>

Output:

TEXT 📖 Display only
Output displayed

4. Building a Login System

▶ Example: Complete Login System

Output:

TEXT 📖 Display only
(no visible output)
PHP
<?php
// login.php — Login System
session_start();

// Predefined test users (in a real project, these live in a database)
$users = [
    'admin' => '123456',
    'john' => 'password123',
];

$error = '';

// Already logged in? Redirect to profile
if (isset($_SESSION['user'])) {
    header("Location: profile.php");
    exit;
}

// Handle login request
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username'] ?? '');
    $password = $_POST['password'] ?? '';

    if (isset($users[$username]) && $users[$username] === $password) {
        // Credentials verified — store user in session
        $_SESSION['user'] = [
            'username'    => $username,
            'login_time'  => date("Y-m-d H:i:s"),
            'last_active' => time(),
        ];
        
        // Redirect to profile page
        header("Location: profile.php");
        exit;
    } else {
        $error = "Invalid username or password";
    }
}
?>

<h3>Login</h3>
<?php if ($error): ?>
    <p style="color:red"><?= htmlspecialchars($error) ?></p>
<?php endif; ?>

<form method="POST" action="">
    <p>
        <label>Username:</label>
        <input type="text" name="username" required>
    </p>
    <p>
        <label>Password:</label>
        <input type="password" name="password" required>
    </p>
    <button type="submit">Log In</button>
</form>
<p style="color:#888">Test account: admin / 123456</p>

Output:

TEXT 📖 Display only
Username: admin
Logged in at: 2025-01-15 10:30:00
PHP
<?php
// profile.php — Profile Page (requires login)
session_start();

// Not logged in? Redirect to login
if (!isset($_SESSION['user'])) {
    header("Location: login.php");
    exit;
}

$user = $_SESSION['user'];
?>

<h2>Profile</h2>
<p>Username: <?= htmlspecialchars($user['username']) ?></p>
<p>Logged in at: <?= $user['login_time'] ?></p>

<a href="logout.php">Log Out</a>

(1) Logging Out

PHP
<?php
// logout.php
session_start();

// Option 1: Clear only the user data
unset($_SESSION['user']);

// Option 2: Wipe the entire session
session_unset();    // Clear the $_SESSION array
session_destroy();  // Delete the server-side session file

// Redirect to login
header("Location: login.php");
exit;
?>
Operation Function What It Does
Remove single item unset($_SESSION['key']) Deletes a specific key
Clear all variables session_unset() Empties $_SESSION
Delete session file session_destroy() Removes server-side session data
Delete cookie setcookie(session_name(), '', time()-3600, '/') Removes the PHPSESSID cookie from the browser
💡 Tip: The standard logout sequence: session_unset()session_destroy() → delete the PHPSESSID cookie → redirect to the login page.


5. The Session Lifecycle

TEXT 📖 Display only
User visits for the first time → PHP creates a session file (e.g., sess_abc123)
                ↓
          Data is written to $_SESSION
                ↓
          Cookie sent: PHPSESSID=abc123 to the browser
                ↓
Next visit → Browser sends PHPSESSID=abc123
                ↓
          PHP finds sess_abc123, loads data into $_SESSION
                ↓
... User leaves (closes browser or is idle for a long time) ...
                ↓
Garbage collection → Expired session files are deleted

Sessions expire by default after 24 minutes (session.gc_maxlifetime = 1440 seconds in php.ini). The clock starts from the file's last modification time, not the user's last activity.


6. Session Security Configuration

PHP
<?php
// Configure before session_start()
ini_set('session.cookie_httponly', 1);    // JS can't read the session cookie (XSS protection)
ini_set('session.cookie_secure', 1);      // HTTPS only (required for production)
ini_set('session.cookie_samesite', 'Lax'); // CSRF mitigation
ini_set('session.use_strict_mode', 1);    // Reject uninitialized session IDs

session_start();
?>
💡 Tip: session.use_strict_mode = 1 prevents attackers from fabricating a Session ID. If an attacker invents a non-existent ID, PHP rejects it and creates a fresh session instead.


7. Cookies vs Sessions at a Glance

Cookie Session
Data location User's browser Server
Security Low (user can view/edit) High (user never sees the data)
Capacity 4KB Unlimited (limited only by server disk)
Performance Sent with every request No bandwidth cost (server-side lookup)
Dependency Standalone Depends on cookies (for Session ID)
Best for Preferences, light state Login, permissions, shopping carts

▶ Example: Session Destroy and Regenerate ID

Output:

TEXT 📖 Display only
Page views this session: " . value['views'] . "<br>
Session destroyed and ID regenerated
PHP
<?php
session_start();

$_SESSION['views'] = ($_SESSION['views'] ?? 0) + 1;
echo "Page views this session: " . $_SESSION['views'] . "<br>";

if (isset($_GET['reset'])) {
    session_unset();
    session_destroy();
    session_start();
    session_regenerate_id(true);
    echo "Session destroyed and ID regenerated";
}
?>
<a href="?reset=1">Reset Session</a>

Output:

TEXT 📖 Display only
Output displayed

❓ FAQ

Q Does the session disappear when I close the browser?
A The session data still exists on the server (waiting for garbage collection), but the PHPSESSID cookie in the browser typically disappears when the browser closes. The next time you open the browser, there's no Session ID, so PHP creates a brand new session.
Q If multiple users log in at the same time, do their sessions interfere?
A No. Every user gets their own session with a unique Session ID. $_SESSION always belongs to the current user — there's no cross-contamination.
Q Can sessions work if the user has disabled cookies?
A Not by default, because the Session ID travels via cookie. You can pass it through the URL (PHPSESSID=abc123), but this is very unsafe — the Session ID ends up in browser history, bookmarks, and server logs.

📖 Summary

📝 Exercises

  1. Deploy the complete login system from the examples above (login.php → profile.php → logout.php).
  2. Add a "Change Password" feature to the profile page (validate against the predefined users array).
  3. Implement simple role-based access: only users with role === 'admin' can see an "Admin Panel" link on the page.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏