ChatGPT解决这个技术问题 Extra ChatGPT

检查 PHP 会话是否已经开始

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

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

但这次我收到了这个警告信息:

注意:未定义的变量:_SESSION

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

如果我使用@session_start,它会让事情正常工作并关闭警告吗?

另请参阅 Stackoverflow 的答案:stackoverflow.com/questions/1545357/…

l
lovelyramos

PHP >= 5.4.0、PHP 7、PHP 8 版本的推荐方式

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();
}

我认为 PHP < 的解决方案有问题5.4. session_id 在第一次启动会话时设置,但在会话关闭时不会删除。因此,例如,如果在您的代码段之前有类似 session_start();session_write_close(); 的代码:那么 if 条件失败但我们没有打开的会话......
@Nicolo Martini 据我了解:脚本顶部以 session_start() 开始的会话在脚本退出时关闭,或者在脚本退出之前调用 session_write_closed() 时。即,当数据写入会话 cookie 并且会话被解锁以供另一个也调用“session_start”的脚本访问时,会话关闭。因此,CLOSING 并不意味着会话被销毁。您可以通过退出当前脚本或调用 session_write_close() 来关闭会话,也可以通过调用 session_start() 再次打开它。至少我的理解。
这仍然是开始会话的好方法吗?因为在链接中没有与此答案相关的内容
@csandreas1 您将从链接中看到 session_status 的描述及其预期的返回值。你的问题的答案是肯定的!
我在某些情况下失败了 - 我成功使用了 if(!isset($_SESSION))
A
Alex

对于 PHP 5.4.0 之前的 PHP 版本:

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

不过,恕我直言,如果您不知道会话是否已启动,您真的应该考虑重构会话管理代码......

也就是说,我的意见是主观的,并且在某些情况下(示例在下面的评论中描述)可能无法知道会话是否开始。


不知道您的会话是否开始并不一定是坏事。如果您是延迟加载(仅在第一次需要时才开始会话),那么您的答案中的测试会非常好。
同样在某些环境中,apache 设置了会话自动启动
测试 session_id() 是否在包含文件中返回空字符串的示例:
如果您不知道它是否是 tarted 的,那么关于重构会话管理的评论并不真正相关。例如,如果将高级功能编码到 WordPress 主题中,您将永远不会知道插件是否已经开始使用会话而不进行检查。编码世界并不总是那么黑白:P
嗯,确实不错。我承认我的评论非常主观 - 我会修改我的答案以反映这一点。
B
BenMorel

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

一段代码在可用时使用 session_status 而在不可用时使用旧方法似乎在这里是完美的顺便说一句,提示提示:)
感谢本杰明的更新。很高兴知道从 PHP 5.4 开始可以使用一种新方法。
这是一个更好的检查方法,你并不总是知道你是否启动了一个会话,尤其是当用户在浏览网站的过程中清除 cookie 时......我总是为 2 岁的孩子编写代码,你永远不知道用户会做什么;-) 至于我自己,我有一个小的 Config.php 文件,我的所有脚本都会调用它来设置变量和其他信息,所以只要在该文件中添加它就可以确保会话在以下情况下启动这是必需的
D
Dharman

你可以做到这一点,这真的很容易。

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

@zloctb:我想不出我会做$_SESSION=array();的任何情况,所以这个答案似乎还可以。
@halfer 见 Ryan 的回答。如果已调用 session_destroy(),则仍可以设置 $_SESSION。此外,在单元测试中,您可以直接设置 $_SESSION。但我赞成这一点,因为对于大多数实际情况,这个答案应该足够好(直到 PHP 5.3 再也见不到了......)
k
k.bon
if (version_compare(phpversion(), '5.4.0', '<')) {
     if(session_id() == '') {
        session_start();
     }
 }
 else
 {
    if (session_status() == PHP_SESSION_NONE) {
        session_start();
    }
 }

y
y o

在 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 之前,您应该设置一个全局布尔值。


s
supersuphot

适用于所有 php 版本

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

同样,也可以做 if ((defined('PHP_SESSION_ACTIVE') && session_status() !== PHP_SESSION_ACTIVE) || !session_id())
E
Elshan

检查这个:

<?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


B
BenMorel

使用 session_id(),如果未设置则返回空字符串。它比检查 $_COOKIE 更可靠。

if (strlen(session_id()) < 1) {
    session_start();
}

M
Mahesh Cheliya
if (session_id() === "") { session_start(); }

希望能帮助到你 !


D
Dustin Poissant

这应该适用于所有 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();
    }
  }
}

u
user3140580

你唯一需要做的是:

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

这是我多年来一直使用的。有人建议不要使用这个吗?当然,有时检查会话是否启动是很好的——在某些环境中,apache 设置了会话自动启动、延迟加载(仅在第一次需要时启动会话)或者只是有时需要快速破解
上面是否有相同的反应(@miyuru)
A
Alex Khimich

不确定这种解决方案的效率,但这是来自工作项目 如果您需要定义默认语言,也可以使用这

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

c
crabbly

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

session_start 之前添加 @ 告诉 PHP 避免打印错误消息。

例如:

在您已经将某些内容打印到浏览器后使用 session_start() 会导致错误,因此 PHP 将显示类似“无法发送标头:从(第 12 行)开始”,在这种情况下 @session_start() 仍然会失败,但是错误信息未打印在屏幕上。

在包含文件或重定向到新页面之前使用 exit() 函数,否则会出错。

此代码可用于所有情况:


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


L
Lucas M. Oliveira

在 PHP 5.3 这对我有用:

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

那么你有。如果你不把 not at if 语句开始,会话将以任何方式开始,我不知道为什么。


佚名

基于@Meliza Ramos 响应(见第一个响应)和 http://php.net/manual/en/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();
        }
    }

T
Thielicious
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 文件,您可以在其中通过选择菜肴并删除/添加或更改订单来配置餐厅的菜单。我工作的服务器没有实际版本,所以我让它更灵活。这取决于作者希望使用和尝试它。


N
NiroshanJ

这个代码片段对你有用吗?

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

M
Marcello B.

这是我用来确定会话是否已开始的方法。通过使用 empty 和 isset 如下:

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

这个答案与 2013 年的任何答案都没有什么不同。
S
SamT

您应该重新组织代码,以便在每次执行页面时只调用一次 session_start()


在某些情况下,可能不希望每页执行只调用一次。
如果您要终止会话以重新创建它,那么当然可以,但这是一种特殊情况。一般来说,应用程序的代码应该在一开始就运行一次,这就是 session_start() 的所在。
例如,一个应用程序将会话存储在一个文件中,并且需要加载 2 个并发的慢速数据请求,这些请求都不需要会话,但是一个会阻塞另一个,因为 session_start 锁定了会话文件。
确切地。 @YuriKolovsky 是对的。亚历克斯的问题是中肯的,因为这些情况可能会发生,而且并不少见。
-1,大多数网站都是 CMS 驱动的,并且有诸如主题和插件之类的东西,通常由不同的方编写,永远不知道彼此的代码是否已经开始会话。这只是一个代码组织问题的暗示是错误的。
C
Christian Kruse

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();
    }
}

4
4b0

根据我的实践,在访问 $_SESSION[] 之前,您需要每次调用 session_start 才能使用该脚本。有关手册,请参阅下面的链接。

http://php.net/manual/en/function.session-start.php

对我来说,至少 session_start 作为一个名字是令人困惑的。 session_load 可以更清楚。


L
Leo Tahk

我最终对状态进行了双重检查。 php 5.4+

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

G
Grant Miller

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

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

有效答案更详细。
T
Tunaki
session_start();
if(!empty($_SESSION['user']))
{     
  //code;
}
else
{
    header("location:index.php");
}

N
Nikolay Mihaylov

session_start(); 替换为:

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

它包含代码错误,并且只有在同一个文件被多次包含时才有效,但如果在闭包中则无效。