【问题标题】:Session data not passed to other pages会话数据未传递到其他页面
【发布时间】:2013-06-09 03:48:06
【问题描述】:

我面临的问题有两个:

  1. 我想使用我的会话包装类来创建 跨多个页面的会话。
  2. 想要在设置的超时后使上述会话过期的方法。

作为一个示例用例,如果我的网站需要在访问页面之前进行身份验证,我将创建会话包装器的实例,如果用户的凭据有效,那么我会将它们重定向到帐户页面。

// index.php
if (invalidUser) {
   // Show error
} else if(userIsValid($user_email, $user_pass)) {
   $sess = new Session("MySite", 10);
   Utils::redirect("accountPage.php"); 
}

这是重定向到帐户页面的实用方法:

// utils.php
ob_start(); // Start output buffer
/**
  * Redirects the HTTP header to another location.
  *
  * @param (String) $address the new location to send the browser.
  */
  public static function redirect($address) {
     header("Location: $address");
     exit();
  }

这里是会话包装类的实现:

// session.php
class Session {        
       /**
         * Default Constructor.
         *
         * @param (String) $name the name of the session, as well as the session cookie name 
         * @param (String) $timeout the amount of time to permit the existence of 
         * this session.
         * -1, indicates that the session should live on indefinetely.
         */
        function __construct($name, $timeout = -1) {
            session_name($name);
            session_start();

            $_SESSION["timeout"] = $timeout;
            $_SESSION["created"] = time();
        }

    /**
     * Determines if the session is still considered "alive" based on its 
     * timeout + creation time.
     * If the session has expired we remove the session effectively "Timing out".
     */
    public static function isExpired() {

        // Default infinite timeout case
        if ($_SESSION["created"] == -1) {
            return false;
        }

        // Evaluate time left on session
        if(($_SESSION["timeout"] + $_SESSION["created"]) <= time()) {
            // Remove Session
            return true; 
        } else {
            // Session has not expired yet
            return false;
        }
    }
}

我希望此页面上的 $_SESSION global 数组中的数据是 NULL。我读过类似的帖子,但我想我的具体实现遗漏了一些东西。

// accountsPage.php
<?php
include_once("session.php");

Session::isExpired(); => false
print_r($_SESSION); => NULL

我知道它部分有效,因为如果我不重定向然后打印 $_SESSION global 数组,则其中有数据。我知道在每个页面的开头添加 session_start(),但我想减轻创建额外会话和 cookie 的负担。

提前感谢任何帮助!

【问题讨论】:

    标签: session session-variables php


    【解决方案1】:

    您的Session::isExpired 通过返回FALSE 表现正确,因为未找到请求的$_SESSION 的索引并且它不在同一个session_name 下。

    假设您在第一页上调用了new Session('MyWebsite', 10);。在其他页面中,您需要在开始会话之前调用 MyWebsite 会话名称并获取 $_SESSION 值。

    如果开发人员未指定需要调用哪个会话名称,则会话名称将为每个新请求重置为默认名称。这就是为什么它会返回null。我正在稍微更改您的代码。

    function __construct($name, $timeout = -1) {
       session_name($name);
       session_start();
    
       if(!isset($_SESSION['created'])) {
          $_SESSION["timeout"] = $timeout;
          $_SESSION["created"] = time();
       }
    }
    
    public function isExpired() {
       /* your code here */
    }
    

    我正在从 isExpired() 中获取静态,静态没有调用类构造函数。第二页示例

    <?php
    include('session.php');
    
    $session = new Session('MyWebsite', 10);
    $session->isExpired();
    print_r($_SESSION);
    

    【讨论】:

      【解决方案2】:

      您必须在发送每个页面的输出之前调用session_start()。对于“accountsPage.php”,您确实包含了“session.php”文件,但该文件仅定义了类,它实际上并没有调用此函数,除非您在页面代码中的某处有new Session("MySite", 10);

      我建议您实际上从__construct 中删除session_name($name);session_start();,而是将它们放在“session.php”脚本的顶部。显然,您需要将 $name 替换为 "MySite"(硬编码),但有一些方法可以解决。

      【讨论】:

      • 这很好,但是有没有一种方法可以命名我创建“session.php”实例时创建的会话cookie?
      猜你喜欢
      • 2012-06-17
      • 1970-01-01
      • 2016-11-22
      • 2014-03-28
      • 2017-02-12
      • 2018-04-13
      • 2015-11-04
      • 2017-05-08
      • 2015-01-10
      相关资源
      最近更新 更多