How to tell if a session is active? [duplicate]
Per request, there are a few different ways that you can tell whether or not a session has been started, such as:
$isSessionActive = (session_id() != "");
Or:
$isSessionActive = defined('SID');
However, these both fail if you start a session, then close it; session_id()
will return the prior session's ID, while SID
will be defined. Likewise, calling session_start()
at this point will generate an E_NOTICE
if you already have a session active. Is there a sane way to check if a session is currently active, without having to resort to output buffering, the shut-up operator (@session_start()
), or something else equally as hacky?
EDIT: I wrote a patch to try to get this functionality included in PHP: http://bugs.php.net/bug.php?id=52982
EDIT 8/29/2011: New function added to PHP 5.4 to fix this: "Expose session status via new function, session_status"
// as of 8/29/2011
$isSessionActive = (session_status() == PHP_SESSION_ACTIVE);
EDIT 12/5/11: session_status() on the PHP manual.
See edits to the original question; basically, PHP 5.4 and above now has a function called session_status()
to solve this problem!
"Expose session status via new function, session_status" (SVN Revision 315745)
If you need this functionality in a pre-PHP 5.4 version, see hakre's answer.
I worked around this by adding a couple wrapper functions around the various session creation/closing/destroying functions. Basically:
function open_session() {
session_start();
$_SESSION['is_open'] = TRUE;
}
function close_session() {
session_write_close();
$_SESSION['is_open'] = FALSE;
}
function destroy_session() {
session_destroy();
$_SESSION['is_open'] = FALSE;
}
function session_is_open() {
return($_SESSION['is_open']);
}
Hackish, but accomplished what I needed.
I'm running into this as well, and a setting in $_SESSION
is not an option for me. For PHP 5.3.8:
- If any session has been started with the request,
define('SID')
will returnFALSE
, as well as$_SESSION
is unset. - This is independent whether or not
session_id()
has been used to set a session id or not. - After the first
session_start()
,SID
is defined and$_SESSION
is set to an empty array. -
session_destroy()
does unset thesession_id()
, it's an empty string then.SID
will remain defined (and set to it's previous value which might be an empty string).$_SESSION
is left unchanged. It will get reset/populated next timesession_start
is called.
With these states, especially as session_id()
can be called in between to set the id for the next session, it's not possible to safely determine the session status with SID
, $_SESSION
and session_id()
.
"Trying" with session_start()
(e.g. with @
) might not be really helpful, as this will change the session status and changing the contents of $_SESSION
(and adding a set-cookie header if the cookie was not part of the request). It was not fitting in my case.
While I was running tests, I came across the behaviour, that you can not try to change the ini setting of session.serialize_handler
when the session is active, not even when you set it to the same value. Same is true for session.use_trans_sid
Docs which is more lightweight. This lead me to the following function:
/**
* @return bool
*/
function session_is_active()
{
$setting = 'session.use_trans_sid';
$current = ini_get($setting);
if (FALSE === $current)
{
throw new UnexpectedValueException(sprintf('Setting %s does not exists.', $setting));
}
$result = @ini_set($setting, $current);
return $result !== $current;
}
As far as I can see, the error is checking for active session status only (not disabled), so this should not return a false positive when sessions are disabled.
To get this function compatible with PHP 5.2, it needs a little modification:
/**
* @return bool
*/
function session_is_active()
{
$setting = 'session.use_trans_sid';
$current = ini_get($setting);
if (FALSE === $current)
{
throw new UnexpectedValueException(sprintf('Setting %s does not exists.', $setting));
}
$testate = "mix$current$current";
$old = @ini_set($setting, $testate);
$peek = @ini_set($setting, $current);
$result = $peek === $current || $peek === FALSE;
return $result;
}
Some sandbox.
The following code only dumps one session_id() for me, not two
session_start();
echo session_id();
session_destroy();
echo session_id();
If you're having difficulties with this still you can try creating a variable to check, that you destroy when you destroy the session.
session_start();
$_SESSION['intialized'] = 'This will not print';
$_SESSION = array(); // Unset all variables
session_destroy();
echo $_SESSION['initialized']; // No output
Here's a good drop in replacement that won't break stuff when you move to 5.4:
if(!function_exists('session_status')){
function session_active(){
return defined('SID');
}
}else{
function session_active(){
return (session_status() == PHP_SESSION_ACTIVE);
}
}