检查PHP会话是否已经开始


461

我有一个PHP文件,有时从启动会话的页面调用该文件,有时从没有会话启动的页面调用。因此,当我使用session_start()此脚本时,有时会收到“会话已开始”的错误消息。为此,我放置了以下几行:

if(!isset($_COOKIE["PHPSESSID"]))
{
  session_start();
}

但是这次我收到了以下警告消息:

注意:未定义的变量:_SESSION

有没有更好的方法来检查会话是否已经开始?

如果我使用@session_start它,它将使一切正常运行,只是关闭警告?



Answers:


761

PHP> = 5.4.0和PHP 7版本的推荐方法

if (session_status() == PHP_SESSION_NONE) {
    session_start();
}

参考:http : //www.php.net/manual/en/function.session-status.php

对于PHP <5.4.0版本

if(session_id() == '') {
    session_start();
}

1
我认为PHP <5.4的解决方案存在问题。session_id在会话第一次启动时被设置,但是在会话关闭时不会被删除。因此,举例来说,如果有,您的片段,像代码之前session_start();session_write_close();:那么,如果条件不满足,但我们还没有开,盘中...
尼科洛尼

@Nicolo Martini据我所知:从session_start()脚本顶部开始的会话在脚本退出时或在session_write_closed()脚本退出之前被调用时被关闭。即,当会话的数据被写入会话cookie,并且该会话被另一个也称为“ session_start”的脚本访问时,会话关闭。因此,CLOSING并不意味着该会话已被销毁。您可以通过退出当前脚本或调用关闭会话session_write_close(),也可以通过调用再次打开会话session_start()。我的理解,至少。
Stefan

1
这仍然是开始会议的好方法吗?因为在链接中没有与此答案相关的内容
csandreas1

@ csandreas1,您将从链接中看到session_status的描述及其预期的返回值。您的问题的答案是肯定的!
lovelyramos

我在某些情况下遇到了这种失败-我成功地使用了if(!isset($ _ SESSION))
斯科特

161

对于PHP 5.4.0之前的PHP版本:

if(session_id() == '') {
    // session isn't started
}

但是,恕我直言,如果您不知道是否启动会话,则应该考虑重构会话管理代码。

就是说,我的意见是主观的,在某些情况下(以下示例中描述了这些示例),可能无法知道会话是否开始。


37
不知道会话是否开始并不一定很坏。如果您正在延迟加载(仅在第一次需要时才开始会话),那么答案中的测试将是完美的。
drewm 2011年

1
同样在某些环境中,apache设置了会话自动启动功能
LeonardChallis 2012年

测试session_id()是否在包含文件中返回空字符串的示例:
tgoneil

3
关于重构会话管理的评论(如果您不知道它是否变脏了)不是很重要。例如,如果将高级功能编码为WordPress主题,您将永远不知道插件是否已经开始使用会话而不进行检查。编码世界并不总是那么黑:P
Jimbo Jonny 2012年

嗯,确实不错。我承认我的评论非常主观-我将修改答案以反映这一点。
亚历克斯

71

PHP 5.4引入了session_status(),它比依靠可靠session_id()

考虑以下代码段:

session_id('test');
var_export(session_id() != ''); // true, but session is still not started!
var_export(session_status() == PHP_SESSION_ACTIVE); // false

因此,要检查会话是否已启动,现在建议使用PHP 5.4:

session_status() == PHP_SESSION_ACTIVE

3
一小段使用session_status的代码片段,以及在不可用时使用较旧方法的代码片段,此处似乎是完美的BTW,提示提示:)
Jimbo Jonny 2012年

1
感谢您的更新本杰明。很高兴知道从PHP 5.4开始可以使用一种新方法。
Logan

1
这是一种更好的检查方法,您并不总是知道是否已启动会话,尤其是当用户在浏览网站的过程中清除Cookie时……我总是为2岁的孩子编写代码,永远不知道用户会做什么;-)至于我自己,我有一个小的Config.php文件,该文件在我所有的脚本上都被调用以设置变量和其他信息,因此只要在文件中添加此文件,就始终可以确保会话启动它是必要的
Andy Braham 2013年

35

您可以做到这一点,而且非常容易。

if (!isset($_SESSION)) session_start();

希望能帮助到你 :)


6
@zloctb:我想不出我会做的任何情况$_SESSION=array();,所以这个答案似乎还可以。
2013年

5
@halfer请参阅Ryan的答案。如果session_destroy()已被调用,则$_SESSION仍可以设置。另外,在单元测试中,您可以$_SESSION直接进行设置。但是我对此表示赞同,因为在大多数实际情况下,这个答案应该足够好(直到不再出现PHP 5.3为止……)
Darren Cook

22
if (version_compare(phpversion(), '5.4.0', '<')) {
     if(session_id() == '') {
        session_start();
     }
 }
 else
 {
    if (session_status() == PHP_SESSION_NONE) {
        session_start();
    }
 }

21

在PHP 5.4之前,除了设置全局标志之外,没有其他可靠的方法。

考虑:

var_dump($_SESSION); // null
session_start();
var_dump($_SESSION); // array
session_destroy();
var_dump($_SESSION); // array, but session isn't active.

要么:

session_id(); // returns empty string
session_start();
session_id(); // returns session hash
session_destroy();
session_id(); // returns empty string, ok, but then
session_id('foo'); // tell php the session id to use
session_id(); // returns 'foo', but no session is active.

因此,在PHP 5.4之前,您应该设置一个全局布尔值。


12

对于所有PHP版本

if ((function_exists('session_status') 
  && session_status() !== PHP_SESSION_ACTIVE) || !session_id()) {
  session_start();
}

1
同样,也可以这样做if ((defined('PHP_SESSION_ACTIVE') && session_status() !== PHP_SESSION_ACTIVE) || !session_id())
Anthony Hatzopoulos 2014年

9

检查一下:

<?php
/**
* @return bool
*/
function is_session_started()
{
    if ( php_sapi_name() !== 'cli' ) {
        if ( version_compare(phpversion(), '5.4.0', '>=') ) {
            return session_status() === PHP_SESSION_ACTIVE ? TRUE : FALSE;
        } else {
            return session_id() === '' ? FALSE : TRUE;
        }
    }
    return FALSE;
}

// Example
if ( is_session_started() === FALSE ) session_start();
?>

来源http://php.net




5

这应该适用于所有PHP版本。它确定PHP版本,然后检查是否基于PHP版本启动了会话。然后,如果会话未启动,它将启动它。

function start_session() {
  if(version_compare(phpversion(), "5.4.0") != -1){
    if (session_status() == PHP_SESSION_NONE) {
      session_start();
    }
  } else {
    if(session_id() == '') {
      session_start();
    }
  }
}

4

您唯一需要做的是:

<?php
if(!isset($_SESSION))
{
session_start();
}
?>

这是我多年来使用的那个。有人建议不要使用这个吗?Ofcourse如果会话有时启动它的良好的使用检查-在某些环境中的Apache有会话。自动启动设置,延迟加载(仅在启动时,它的第一需要的会话),或者仅仅是一个有时只是需要做一个快速的黑客
ķ Kilian Lindberg 2014年

上面是相同的响应(@miyuru)

2

不确定这种解决方案的效率,但这是来自正在运行的项目。如果需要定义默认语言,也可以使用此方法

   /**
    * Start session
    * Fall back to ukrainian language
    */
   function valid_session() {
    if(session_id()=='') {
        session_start();
        $_SESSION['lang']='uk';
        $_SESSION['lang_id']=3;
    }
    return true;
  }

2

@ 在函数调用取消函数调用期间可能报告的任何错误之前。

添加一个@before session_start告诉PHP避免打印错误消息。

例如:

使用session_start()你已经打印后的东西到浏览器导致的错误,以便PHP会显示类似“头不能被发送:开始于(12号线)”,@session_start()在这种情况下仍然会失败,但没有印上的错误信息屏幕。

在包含文件或重定向到新页面之前,请使用此exit()功能,否则会产生错误。

此代码可在所有情况下使用:


    <?php 
        if (session_status() !== PHP_SESSION_ACTIVE || session_id() === ""){
            session_start(); 
        }
    ?>

1

在PHP 5.3上,这对我有效:

if(!strlen(session_id())){
    session_name('someSpecialName');
    session_start();
} 

那么你有。如果您不将not at if语句放在开头,那么会话将以任何方式开始,我不这样做。


1

响应基于@Meliza Ramos响应(请参阅第一个响应)和http://php.net/manual/zh/function.phpversion.php

动作:

  • 定义PHP_VERSION_ID(如果不存在)
  • 定义函数以根据PHP_VERSION_ID检查版本
  • 定义函数以确保openSession()安全

只使用openSession()

    // PHP_VERSION_ID is available as of PHP 5.2.7, if our
    // version is lower than that, then emulate it
    if (!defined('PHP_VERSION_ID')) {
        $version = explode('.', PHP_VERSION);

        define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));


        // PHP_VERSION_ID is defined as a number, where the higher the number
        // is, the newer a PHP version is used. It's defined as used in the above
        // expression:
        //
        // $version_id = $major_version * 10000 + $minor_version * 100 + $release_version;
        //
        // Now with PHP_VERSION_ID we can check for features this PHP version
        // may have, this doesn't require to use version_compare() everytime
        // you check if the current PHP version may not support a feature.
        //
        // For example, we may here define the PHP_VERSION_* constants thats
        // not available in versions prior to 5.2.7

        if (PHP_VERSION_ID < 50207) {
            define('PHP_MAJOR_VERSION',   $version[0]);
            define('PHP_MINOR_VERSION',   $version[1]);
            define('PHP_RELEASE_VERSION', $version[2]);

            // and so on, ...
        }
    }

    function phpVersionAtLeast($strVersion = '0.0.0')
    {
        $version = explode('.', $strVersion);

        $questionVer = $version[0] * 10000 + $version[1] * 100 + $version[2];

        if(PHP_VERSION_ID >= $questionVer)
            return true;
        else
            return false;

    }

    function openSession()
    {
        if(phpVersionAtLeast('5.4.0'))
        {
            if(session_status()==PHP_SESSION_NONE)
                session_start();
        }
        else // under 5.4.0
        {
            if(session_id() == '')
                session_start();
        }
    }

1
if (version_compare(PHP_VERSION, "5.4.0") >= 0) {
    $sess = session_status();
    if ($sess == PHP_SESSION_NONE) {
        session_start();
    }
} else {
    if (!$_SESSION) {
        session_start();
    }
}

实际上,现在解决该问题现在为时已晚,现在在这里进行解释。这是我的一个项目的.inc文件,您可以在其中通过选择菜肴并删除/添加或更改订单来为餐厅配置菜单。我正在使用的服务器没有实际版本,因此使它更加灵活。这取决于作者希望使用并尝试一下。


1

该代码段对您有用吗?

if (!count($_SESSION)>0) {
    session_start();
}

0

您应该重新组织代码,以便session_start()每个页面执行一次准确地调用一次。


4
在某些情况下,可能不希望每个页面执行一次准确地调用它。
Timo Huovinen

如果要终止会话以重新创建会话,请确保,但这是一种特殊情况。通常,应用程序应具有从头开始运行一次的代码,这就是session_start()所在的位置。
SamT 2012年

1
例如,一个应用程序将会话存储在一个文件上,并且需要加载2个并发的慢速数据请求,这些请求都不需要会话,但是一个会阻塞另一个请求,因为session_start会锁定会话文件。
Timo Huovinen

究竟。@YuriKolovsky是正确的。亚历克斯的问题是相关的,因为这些情况有可能发生,而且并不少见。
Paulo Coghi-恢复莫妮卡2012年

14
-1,大多数网站都是由CMS驱动的,并且通常由不同的各方编写诸如主题和插件之类的东西,却不知道彼此的代码是否已经开始会话。这仅是代码组织问题的暗示是错误的。
Jimbo Jonny 2012年

0
session_start();
if(!empty($_SESSION['user']))
{     
  //code;
}
else
{
    header("location:index.php");
}

0

PHP_VERSION_ID自PHP 5.2.7起可用,因此请首先进行检查,必要时进行创建。 session_status从PHP 5.4开始可用,因此我们也必须检查以下内容:

if (!defined('PHP_VERSION_ID')) {
    $version = explode('.', PHP_VERSION);
    define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
}else{
    $version = PHP_VERSION_ID;
}
if($version < 50400){
    if(session_id() == '') {
        session_start();
    }
}else{
    if (session_status() !== PHP_SESSION_ACTIVE) {
        session_start();
    }
}


0

我最终仔细检查了状态。PHP 5.4以上

if(session_status() !== PHP_SESSION_ACTIVE){session_start();};
if(session_status() !== PHP_SESSION_ACTIVE){die('session start failed');};

0

您可以使用以下解决方案来检查PHP会话是否已经启动:

if(session_id()== '')
{
   echo"Session isn't Start";
}
else
{
    echo"Session Started";
}

有效答案更加详细。
克莱门特PREVOST

0

这就是我用来确定会话是否已开始的内容。通过使用empty和isset,如下所示:

if (empty($_SESSION)  && !isset($_SESSION))  {
    session_start();
}

-3

替换session_start();为:

if (!isset($a)) {
    a = False;
    if ($a == TRUE) {
        session_start();
        $a = TRUE;
    }
}

它包含代码错误,并且仅当多次包含同一个文件时才起作用,但如果在闭包内则不起作用。
BananaAcid
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.