If PHP appears to keep you logged in after logout, clear three separate things: the session values in the current request, the server-side session data, and the browser’s session cookie. session_destroy() handles only the server-side data; by itself, it does not clear $_SESSION or remove the cookie that carries the session ID.
Why session_destroy() may not log you out
PHP’s session_destroy() documentation says the function destroys data associated with the current session. It does not unset the session-related global variables or the browser’s session cookie. That means the logout request can still see values already loaded into $_SESSION, and the browser can continue sending the old session ID unless the cookie is removed.
As an Amazon Associate I earn from qualifying purchases.
Logout therefore has separate server-side and browser-side jobs. Clear the current request’s session array, remove the cookie using the same scope as the login cookie, and then destroy the stored session data. After redirecting, check authentication on a new protected request rather than judging by values still visible during the logout request.
Use this logout sequence
Start the session before changing its values or reading its cookie parameters. This pattern follows the PHP manual’s separation of clearing variables, deleting the cookie, and destroying the session:
#1 Best Overall
<?php
session_start();
// Clear values in this request and the session payload to be saved.
$_SESSION = [];
// Remove the browser cookie using the login cookie's scope.
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();
header('Location: /login', true, 303);
exit;
Replace /login with the appropriate destination for your application. The cookie deletion must use the same cookie name and scope as the login cookie; session_get_cookie_params() supplies the configured path, domain, Secure, and HttpOnly settings rather than requiring guessed values. The PHP manuals for session_get_cookie_params() and setcookie() describe these cookie settings.
Why clear $_SESSION explicitly
Assigning an empty array removes the session values available to the current request. PHP also documents session_unset() as a way to unset session variables while a session is active. Do not use unset($_SESSION) to clear the whole superglobal: PHP warns that doing so disables registering session variables through it.
Rank #2
Why remove the cookie separately
When cookies carry the session ID, the browser must receive an expired cookie with matching scope to stop sending that ID. A cookie deletion with a different path or domain can leave the original cookie in place. The session.use_cookies check avoids attempting this cookie step when PHP is not configured to use cookies for session IDs; in that configuration, investigate the mechanism actually carrying the session ID.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Check what happens on the next request
- Confirm the logout endpoint runs. Verify that it calls
session_start()before accessing$_SESSION, and that the code reaches the cleanup and redirect. - Inspect the logout response. Look for a
Set-Cookieheader expiring the session cookie. Compare its name, path, and domain with the cookie set during login. The cookie parameters should also reflect the intended Secure and HttpOnly settings. - Check for output before headers. Whitespace, a byte-order mark, a PHP warning, or template output before
setcookie()orheader()can prevent the browser from receiving the cookie deletion or redirect headers. - Open a protected URL in a new request. Check whether the application still authenticates that request. Values shown during the logout request can be stale because destroying the session does not erase variables already loaded into that request.
- Look for another login mechanism. A remember-me cookie, JWT, framework guard, reverse-proxy session, or server-side cache may preserve authentication independently of PHP’s session data. Invalidate the mechanism that actually authenticates the request.
- Check the session backend if data appears to return. Confirm the configured handler and
session.save_path. With PHP’s default files handler, session data is persisted on the server; another handler may have its own storage and invalidation behavior.
Account for requests running at the same time
A logout request may overlap with AJAX calls, background requests, or other connections using the same session. The PHP manual warns that immediate session deletion can race with other requests and lead to unexpected results. If authentication appears to return intermittently, check for in-flight requests and determine whether your application needs to coordinate them with logout or reject their work once the user has logged out.
Quick Recap
Rank #4
Keep the two logout checks distinct
| What you are checking | What to verify |
|---|---|
| Server-side session data | session_destroy() ran for the session, and the configured session handler’s storage no longer authenticates it. |
| Browser session cookie | The response expires the cookie using the same name, path, and domain as the login cookie. |
| Current request state | $_SESSION was cleared; do not treat values loaded before destruction as proof that the next request remains logged in. |
| Application authentication | No separate token, remember-me mechanism, framework guard, proxy session, or cache is restoring the login. |
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




