Php 为什么我的饼干没有凝固?
我有以下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
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