【问题标题】:$_SESSION variable is null before I set it to null$_SESSION 变量在我将其设置为 null 之前为 null
【发布时间】:2018-07-29 07:34:31
【问题描述】:

我在我正在构建的网站的php 代码中遇到了一个奇怪的问题:

我使用超全局 $_SESSION['recent'] 在我的网页上创建警报。例如,如果用户尝试登录,但输入了错误的密码,登录表单会将其数据发送到文件login.php,该文件会检查所有数据是否正确。如果数据正确,它将设置$_SESSION['recent'] = 'login_succes'(以及其他一些内容,以便用户登录),否则它将设置$_SESSION['recent'] = 'login_fail'。接下来会以header('location: http://www.example.com/')返回首页。

在这个主页中,有一段php 代码带有switch 语句,它检查所有可能的$_SESSION['recent'] 值并根据其值发出警报。这段代码有点像这样(我用的是bootstrap):

<?php switch ($_SESSION['recent']) { ?>
<?php case 'logout': ?>
<div class="container-fluid alert-fixed"><div class="alert alert-success alert-dismissible">
    <button type="button" class="btn close" data-dismiss="alert">&times;</button>
    You are signed out.
</div></div>
<?php break; case 'login_succes': ?>
<div class="container-fluid alert-fixed"><div class="alert alert-success alert-dismissible">
    <button type="button" class="close" data-dismiss="alert">&times;</button>
    You are signed in
</div></div>
<?php break; case 'login_fail': ?>
... (similar alert message)
<?php break; case 'not_loggedin': ?>
...
<?php break; case 'admin_change_succes': ?>
...
<?php break; case 'admin_change_fail': ?>
...
<?php break; } $_SESSION['recent'] = null; ?>

所以我期望它会检查任何通知并在必要时显示警报消息。完成后,它会设置$_SESSION['recent'] = null,这样这条消息就不会一直显示。

然而,这是问题所在:这适用于前 3 个案例(logoutlogin_succeslogin_fail),但对于所有其他案例,警报不会显示,除非我删除 $_SESSION['recent'] = null; 行(我显然不想删除,因为这样警报消息将在重新加载时继续显示)。

有谁知道是什么原因造成的以及如何解决这个问题?如果您需要更多信息,请直接询问。

谢谢!

【问题讨论】:

  • 这个文件的 PHP 文件开头是否有session_start();?此外,您可以取消设置变量 unset($_SESSION['recent']),而不是 $_SESSION['recent'] = null。
  • 是的,它确实有 session_start() 并且使用 unset() 也不起作用......
  • 在 switch 语句之前回显 $_SESSION['recent'] 并确保它具有您正在寻找的值。确保这些值与您的大小写值匹配。
  • 我已经这样做了,正如我在问题中提到的那样:当我删除包含 $_SESSION['recent'] = null; 的行时,警报工作得很好
  • @wohe1 我认为您的代码没有问题,它应该可以按预期工作,但现在取决于程序控制如何到达此文件。

标签: php switch-statement session-variables


【解决方案1】:

您发布的相关代码看起来应该可以按预期工作。问题很可能出在外面的某个地方。为了确保您可以访问会话值并在脚本完成时将其清除,您可以执行以下操作

  1. 添加文件FlashMessages.php,内容如下

    <?php
    class FlashMessages {
        private static $messages;
        private static $sessionStarted = false;
    
        public function __construct() {
            if (!self::$sessionStarted) {
                session_start();
                self::$sessionStarted = true;
            }
        }
    
        public function getMessage($name) {
            if (!array_key_exists($name, self::$messages)) {
                self::$messages[$name] = array_key_exists($name, $_SESSION) ? $_SESSION[$name] : null;
                unset($_SESSION[$name]);
            }
    
            return self::$messages[$name];
        }
    }
    
  2. 在需要检查的地方添加下一个代码

    <?php
    require_once('FlashMessages.php');
    $flashMessages = new FlashMessages();
    switch ($flashMessages->getMessage('recent')) {
        //...your code goes here
    }
    

【讨论】:

    【解决方案2】:

    所以我找到了自己的解决方案(以上所有方法都不适合我...):

    在我的代码中,我会检查如下错误:

    if (!$_SESSION['uid'] or !$_SESSION['login']) {
        $_SESSION['recent'] = 'not_loggedin';
        header('location: http://my.domain.com/');
    }
    

    但是,在该块之后还有很多其他代码。我认为header 语句会阻止执行以下代码,但似乎并非如此,将代码更改为以下代码对我有用:

    if (!$_SESSION['uid'] or !$_SESSION['login']) {
        $_SESSION['recent'] = 'not_loggedin';
        header('location: http://my.domain.com/');
        die();
    }
    

    【讨论】:

    • 嗯,现在很清楚问题出在哪里了。当您在 switch 运算符结束后将 null 分配给会话变量时,您需要在 switch 正文中以某种方式阻止它。 die() 是一种选择。另一种选择是将$_SESSION['recent'] = null; 移动到switch 块上方。但是,您需要先将$_SESSION['recent'] 分配给变量,然后将此变量用作标准。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多