为什么我的 Cookie 未设置?更好的解决方案

2022-08-30 15:02:07

我有以下PHP函数:

function validateUser($username){
    session_regenerate_id (); 
    $_SESSION['valid'] = 1;
    $_SESSION['username'] = $username;
    setcookie('username2',$username,time()+60*60*24*365);
    header("Location: ../new.php");
}

然后我拿起饼干:

echo $_COOKIE['username2']; exit();

(我只是为了调试目的而放的)exit()

唯一的问题是,它是空白的。有什么想法吗?

更新:这是函数的调用方式:

    if(mysql_num_rows($queryreg) != 0){
    $row = mysql_fetch_array($queryreg,MYSQL_ASSOC);
    $hash = hash('sha256', $row['salt'] . hash('sha256', $password));
    if($hash == $row['password']) {
        if($row['confirm'] == 1){
            if(isset($remember)){
                setcookie('username',$username,time()+60*60*24*365);
                setcookie('password',$password,time()+60*60*24*365);
            } else {
                setcookie('username','',time()-3600);
                setcookie('password','',time()-3600);
            }
            validateUser($username);

我没有包括所有语句以节省一些空间。if()


答案 1

尝试添加 path = /,以便 cookie 适用于整个站点,而不仅仅是当前目录(之前已经吸引了我)

setcookie('password',$password,time()+60*60*24*365, '/'); 

还要确保cookie是php手册中建议输出的第一件事(这之前也抓住了我)

与其他标头一样,Cookie 必须在脚本的任何输出之前发送(这是协议限制)。


答案 2

为什么会出现此问题

问题来自 setcookie() 不会立即设置 cookie,它会发送标头,因此浏览器会设置 cookie。这意味着,对于当前页面加载,setcookie() 不会生成任何 .$_COOKIE

当浏览器稍后请求页面时,它会在标头中发送cookie,以便PHP可以以$ _COOKIE的形式检索它们。

简单、旧的解决方案

关于解决方案,显而易见的是:

setcookie('username',$username,time()+60*60*24*365);
// 'Force' the cookie to exists
$_COOKIE['username'] = $username;

更好的解决方案

我创建了一个类,它解决了 setcookie() 和 $_COOKIE 共享的问题:Cookie

// Class that abstracts both the $_COOKIE and setcookie()
class Cookie
  {
  // The array that stores the cookie
  protected $data = array();

  // Expiration time from now
  protected $expire;
  // Domain for the website
  protected $domain;

  // Default expiration is 28 days (28 * 3600 * 24 = 2419200).
  // Parameters:
  //   $cookie: $_COOKIE variable
  //   $expire: expiration time for the cookie in seconds
  //   $domain: domain for the application `example.com`, `test.com`
  public function __construct($cookie, $expire = 2419200, $domain = null)
    {
    // Set up the data of this cookie
    $this->data = $cookie;

    $this->expire = $expire;

    if ($domain)
      $this->domain = $domain;
    else
      {
      $this->domain = 
        isset($_SERVER['HTTP_X_FORWARDED_HOST']) ?
        $_SERVER['HTTP_X_FORWARDED_HOST'] :
        isset($_SERVER['HTTP_HOST']) ?
          $_SERVER['HTTP_HOST'] :
          $_SERVER['SERVER_NAME'];
      }
    }

  public function __get($name)
    {
    return (isset($this->data[$name])) ?
      $this->data[$name] :
      "";
    }

  public function __set($name, $value = null)
    {
    // Check whether the headers are already sent or not
    if (headers_sent())
      throw new Exception("Can't change cookie " . $name . " after sending headers.");

    // Delete the cookie
    if (!$value)
      {
      setcookie($name, null, time() - 10, '/', '.' . $this->domain, false, true);
      unset($this->data[$name]);
      unset($_COOKIE[$name]);
      }

    else
      {
      // Set the actual cookie
      setcookie($name, $value, time() + $this->expire, '/', $this->domain, false, true);
      $this->data[$name] = $value;
      $_COOKIE[$name] = $value;
      }
    }
  }

然后你可以像这样使用它:

$Cookie = new Cookie($_COOKIE);
$User = $Cookie->user;
$LastVisit = $Cookie->last;
$Cookie->last = time();

当然,你必须把它传递开来。比拥有全球好得多。


推荐