Php 为什么我的饼干没有凝固?

Php 为什么我的饼干没有凝固?,php,cookies,Php,Cookies,我有以下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"); } 然后我去拿饼干: e

我有以下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()
用于调试目的)

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

更新: 函数的调用方式如下:

    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()
语句以节省一些空间。

尝试添加路径=/,这样cookie不仅适用于当前目录,而且适用于整个站点(我以前就发现了这个问题)

范例

setcookie('password',$password,time()+60*60*24*365, '/'); 
还要确保cookie是第一个被输出的东西 正如php手册中所建议的那样(我以前也发现过这一点)

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


下面是setcookie的一般语法

setcookie(name,value,expire,path,domain,secure); 
看第三个参数,如果不设置它,脚本将把它带到当前工作目录。因此,如果未在
a.com/b/setcookie.php
上设置路径而设置cookie,则
a.com/checkcookie.php
将无法使用cookie。您要做的是在子文件夹中设置cookie并重定向到父文件夹,请查看
。/
,因为它不可用,因此出现问题。如何避免这种情况?正常过程是提供一个路径,该路径是
/
,在您的情况下,提供
/
作为第四个参数。cookie的第五个参数将设置它的安全性。有更多的解释。这会解决你的问题。将域路径设置为
domain.com
,将使cookie可用于
domain.com
下的所有内容,但不能用于
something.domain.com
。将domain value设置为
.domain.com
,查看domain.com前面的点,将使其在
anything.domain.com
中可用。嗯

你为什么会有这个问题 问题在于setcookie()不会立即设置cookie,它会发送标题,以便浏览器设置cookie。这意味着,对于当前页面加载,setcookie()将不会生成任何
$\u COOKIE

当浏览器稍后请求页面时,它会发送标题中的COOKIE,以便PHP能够以$\u COOKIE的形式检索它们

简单、古老的解决方案 关于解决方案,显而易见的一点是:

setcookie('username',$username,time()+60*60*24*365);
// 'Force' the cookie to exists
$_COOKIE['username'] = $username;
更好的解决方案 我创建了一个类,
Cookie
,它解决了setcookie()和$\u 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();

当然,你必须传递它。比使用globals要好得多。

我想我会添加另一个可能的原因,解释为什么cookie不能设置或显示随机功能行为

以下情况可能适用于某些程序员,由于不正确使用
header\u remove()

如果您尝试在调用
header\u remove()
之前设置cookie,则将永远不会创建cookie,因为您还立即销毁了为在缓存到客户端之前创建cookie而设置的头

您可能会发现,在摆弄时,您的cookie突然因未知原因而工作,因此您需要了解标题周围的竞争条件:


  • 在第一次运行时,您设置了一个cookie,并且根本不调用
    header\u remove()
  • 在第二次运行时,您可以调用
    header\u remove()
  • 你会发现你的cookie现在总是被设置的,不管条件(2)和它被调用的次数是多少,因为(1)至少发生过一次

    cookie将保持设置状态,直到过期被覆盖
    取消设置()


    当在最终调用
    header\u remove()
    之前修改诸如cookie值之类的头时,同样适用,您将无法设置新值,因为它们将在响应缓冲给用户之前被擦除

    您需要在
    header\u remove()
    之后而不是之前设置Cookie和任何其他标题

    使用
    header\u remove()

    这种情况下的场景示例如下所示:

    使用
    header\u remove()
    更改RESTFUL API的HTTP响应代码层次结构,其中您正在使用
    axios
    拦截器

  • 如果应用程序在任何执行点出错,则应用程序首先设置400+头错误

  • 当达到最终所需的执行点时,将标题修改为200,并期望得到有效响应

  • 在这种情况下,您可能希望保留所有其他先前设置的头,但清除HTTP状态(400?)代码,以便为最终响应设置新的(200?)代码

    如果在删除之前设置的标题之前再次尝试设置标题以更改状态代码,则会出现“Headers ready sent”(标题已发送)错误

    您可以使用删除特定的标题,以下是如何取消设置状态代码并分阶段设置新代码:

    
    //设置默认状态代码
    http_响应_代码(500);
    //启动逻辑运行-如果在此失败,则返回500
    //身份验证逻辑-如果未经授权?
    标题_remove('HTTP/1.0');//清除前500个
    http_响应_代码(401);//设置新的状态代码
    //还有别的吗?
    //返回数据逻辑-成功
    标题_remove('HTTP/1.0');//清除前500个
    http\u response\u code(200)//设置新的状态码
    
    这要求您在任何输出之前调用此函数,包括和标记以及任何空格

    这就是结构的外观

    <?php
    $cookie_name = "user";
    $cookie_value = "Ahmed Moftah";
    setcookie($cookie_name, $cookie_value, time() + (86400 * 30), "/"); // 86400 = 1 day
    ?>
    <?php
    if(!isset($_COOKIE[$cookie_name])) {
        echo "Cookie named '" . $cookie_name . "' is not set!";
    } else {
        echo "Cookie '" . $cookie_name . "' is set!<br>";
        echo "Value is: " . $_COOKIE[$cookie_name];
    }
    ?>
    <html>
    <body>
    
    
    
    </body>
    </html>
    
    
    
    这可能是缓存问题。尝试关闭浏览器并打开一个具有localhost文件路径的新浏览器。我有sa