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:

  1. If any session has been started with the request, define('SID') will return FALSE, as well as $_SESSION is unset.
  2. This is independent whether or not session_id() has been used to set a session id or not.
  3. After the first session_start(), SID is defined and $_SESSION is set to an empty array.
  4. session_destroy() does unset the session_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 time session_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_sidDocs 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);   
    }        
}