Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

PHP Dictionary

  1. Home
  2. PHP Dictionary
  3. session_start() / $_SESSION / session_destroy()

session_start() / $_SESSION / session_destroy()

Since: PHP 4(2000)

Starts a session and stores per-user data on the server. Use it when you need to persist data across pages, such as managing login state or a shopping cart.

Syntax

session_start($options);

// Store and retrieve session variables.
$_SESSION['key'] = $value;

// Destroy the session.
session_destroy();

// Regenerate the session ID.
session_regenerate_id($delete_old_session);

session_id($id);

// Set session cookie parameters.
session_set_cookie_params($options);

Function List

FunctionDescription
session_start($options)Starts a session. Does nothing if a session is already active. You can pass options such as cookie_lifetime and cookie_secure as an associative array.
$_SESSIONA superglobal array that stores session variables. Values saved to this array are available on the next request from the same user.
session_destroy()Destroys all data associated with the current session. Because session variables are not cleared immediately, also set $_SESSION = [] to empty the array.
session_regenerate_id($delete_old)Generates a new session ID. Pass true to also delete the old session file.
session_id($id)Returns the current session ID when called with no argument. Pass a string to set the session ID.
session_set_cookie_params($options)Sets the session cookie parameters. Must be called before session_start().

Sample Code

Call session_start() exactly once at the top of every page, before any output.

session_start.php
<?php
// Start the session.
session_start();

// Store data in session variables.
$_SESSION['username'] = 'Kiryu Kazuma';
$_SESSION['favorite_song'] = 'Baka Mitai';
$_SESSION['login_time'] = time();
echo $_SESSION['username'] . "\n"; // Outputs 'Kiryu Kazuma'.
echo $_SESSION['favorite_song'] . "\n"; // Outputs 'Baka Mitai'.

if (isset($_SESSION['username'])) {
	echo "Logged in as: " . $_SESSION['username'] . "\n";
}

// Check the session ID.
echo session_id() . "\n"; // Outputs an ID like 'abc123def456...'.

// Configure the session cookie with secure settings.
session_set_cookie_params([
	'lifetime' => 0, // Valid until the browser is closed.
	'path' => '/',
	'domain' => '',
	'secure' => true, // Send the cookie over HTTPS only.
	'httponly' => true, // Prevents JavaScript from accessing the cookie.
	'samesite' => 'Lax' // Sets the SameSite attribute as a CSRF countermeasure.
]);
session_start(); // ← In real code, this is the only call to session_start() per page.

// Regenerate the session ID on successful login.
session_regenerate_id(true); // Also deletes the old session file.
$_SESSION['user_id'] = 1;

// Complete logout implementation.
$_SESSION = []; // Clear all session variables.
if (ini_get("session.use_cookies")) {
	$params = session_get_cookie_params();
	setcookie(
		session_name(), '', time() - 42000,
		$params["path"], $params["domain"],
		$params["secure"], $params["httponly"]
	); // Delete the session cookie.
}
session_destroy(); // Destroy the session data.

Running the code produces the following output:

php session_start.php
Kiryu Kazuma
Baka Mitai
Logged in as: Kiryu Kazuma
abc123def456789ghijk012345lmnop

Practical Pattern: Complete Login Implementation

The following sample uses this users table. Passwords should be stored as hashes generated by password_hash().

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(100) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    role VARCHAR(20) DEFAULT 'user'
);

-- Hash of password 'secret123' (generated by password_hash())
INSERT INTO users (email, password_hash, role) VALUES
('kiryu_kazuma@wp-p.info', '$2y$10$xxxxx...', 'admin');

Verify the table contents.

SELECT * FROM users;
+----+------------------------+--------------------------------------------------------------+-------+
| id | email                  | password_hash                                                | role  |
+----+------------------------+--------------------------------------------------------------+-------+
|  1 | kiryu_kazuma@wp-p.info | $2y$10$xxxxx...                                              | admin |
+----+------------------------+--------------------------------------------------------------+-------+
1 row in set
sample_login.php
<?php
// Complete login implementation pattern.
// 1. Configure session cookie parameters before calling session_start().
session_set_cookie_params([
	'lifetime' => 0,
	'path' => '/',
	'secure' => true,
	'httponly' => true,
	'samesite' => 'Lax',
]);
session_start();

// 2. Verify the CSRF token (compare against the token submitted with the form).
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
	if (!isset($_SESSION['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
		http_response_code(403);
		exit('Forbidden');
	}

	$email = $_POST['email'] ?? '';
	$password = $_POST['password'] ?? '';

	// 3. Authenticate the user against the database (stub implementation here).
	$pdo = new PDO('mysql:host=localhost;dbname=sample_db;charset=utf8mb4', 'root', 'password', [
		PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
		PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
	]);
	$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email LIMIT 1");
	$stmt->execute([':email' => $email]);
	$user = $stmt->fetch();
	// Verify the password hash with password_verify().
	if ($user && !password_verify($password, $user['password_hash'])) {
		$user = false;
	}

	if ($user) {
		// 4. Regenerate the session ID immediately on successful login (prevents session fixation).
		session_regenerate_id(true);
		$_SESSION['user_id'] = $user['id'];
		$_SESSION['role'] = $user['role'];
		$_SESSION['login_time'] = time();
		header('Location: /dashboard.php');
		exit;
	} else {
		$_SESSION['error'] = 'Invalid email or password.';
	}
}

// 5. Issue a CSRF token when displaying the form.
if (!isset($_SESSION['csrf_token'])) {
	$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

Use curl commands to verify the behavior. The following shell script retrieves the login form, extracts the CSRF token, and submits a login request.

sample_login_test.sh
#!/bin/bash
# 1. Retrieve the login form and extract the CSRF token.
CSRF=$(curl -c cookie.txt -s http://localhost/login.php \
  | grep -o 'value="[^"]*"' | head -1 | cut -d'"' -f2)
echo "CSRF token: $CSRF"

# 2. Send a login request.
curl -b cookie.txt -c cookie.txt -s -D - \
  -d "email=kiryu_kazuma@wp-p.info&password=secret123&csrf_token=$CSRF" \
  http://localhost/login.php

Running the code produces the following output:

sh sample_login_test.sh
CSRF token: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
HTTP/1.1 302 Found
Location: /dashboard.php
Set-Cookie: PHPSESSID=new_session_id; path=/; secure; HttpOnly; SameSite=Lax

On successful login, a 302 redirect is returned and a new cookie with a regenerated session ID is issued. On authentication failure, the same page is displayed and the error message is stored in $_SESSION["error"].

Common Mistakes

Common mistake 1: output before session_start()

Outputting anything before session_start() causes a "headers already sent" error.

<?php
// NG: Outputting anything before session_start() causes a 'headers already sent' error.
echo "Hello"; // Even whitespace or a blank line triggers this.
session_start(); // Error: Cannot send session cookie - headers already sent

The corrected version is:

<?php
// OK: Call session_start() at the very top of the file, before any output.
session_start();
echo "Hello";

Common mistake 2: session_destroy() only logout

Calling session_destroy() alone does not clear session variables — they remain in memory. Logout requires three steps.

<?php
// NG: Calling session_destroy() alone does not clear session variables.
session_destroy();
echo $_SESSION['username']; // Still accessible in memory.

The corrected version is:

<?php
// OK: Three steps are required: clear variables, delete the cookie, destroy the data.
$_SESSION = [];
if (ini_get("session.use_cookies")) {
	$params = session_get_cookie_params();
	setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]);
}
session_destroy();

Common mistake 3: no session ID regeneration

Not regenerating the session ID after login risks a session fixation attack.

<?php
// NG: Not regenerating the session ID after login risks a session fixation attack.
$_SESSION['user_id'] = $user['id']; // Session fixation risk

The corrected version is:

<?php
// OK: Always regenerate immediately after login.
session_regenerate_id(true);
$_SESSION['user_id'] = $user['id'];

Common mistake 4: duplicate session_start() calls

Calling session_start() again in a required/included file causes an error.

<?php
// NG: Calling session_start() again in a required/included file causes an error.
// common.php: session_start();
// login.php:  require 'common.php'; session_start(); // Warning: session already started

The corrected version is:

<?php
// OK: Check the session status before starting.
if (session_status() === PHP_SESSION_NONE) {
	session_start();
}

session_start() only runs when the status is PHP_SESSION_NONE (not yet started). Use this pattern in shared files that may be included from multiple entry points.

Overview

session_start() initiates PHP's session management and reserves a per-user data area on the server. To prevent session fixation attacks, always call session_regenerate_id(true) to regenerate the session ID immediately after a successful login.

It is important to set the secure, httponly, and samesite attributes on the session cookie. Enabling httponly prevents JavaScript from accessing the cookie, which guards against session hijacking via XSS attacks.

When logging out, you must perform all three steps: clear the session variables, delete the session cookie, and destroy the session data. Calling session_destroy() alone is not enough, because the contents of $_SESSION remain in memory. For cookie operations, also see setcookie().

If you find any errors or copyright issues, please .