下面是一个代码示例:
if (!empty($_GET['supahCookie']))
{
setcookie("myCookie", $_GET['supahCookie'], time()+3600*24*31);
}
$foo = empty($_COOKIE['myCookie'])?'Empty! :(':$_COOKIE['myCookie'];
echo $foo;
输出如下:
空!(
首先看起来setcookie()
是异步执行的,但如果你稍微考虑一下,setcookie()
只是设置了一个cookie头。(小服务器<->浏览器对话)
问题是我需要立即访问新创建的cookie。我该怎么做呢?
我唯一能想到的方法就是这个:
if (!empty($_GET['supahCookie']))
{
setcookie("myCookie", $_GET['supahCookie'], time()+3600*24*31);
unset($_GET['search_type']); // to avoind redirect loop
header('Location: ./?'.http_build_query($_GET));
}
好. .还有一个,有点混乱:
$foo = empty($_GET['supahCookie'])?(empty($_COOKIE['myCookie'])?'Empty! :(':$_COOKIE['myCookie']):$_GET['supahCookie'];
我又在这里瞎折腾了吗?
有人有其他更优雅的解决方案吗?
No。$_COOKIE
和其他超全局变量是作为PHP启动例程的一部分填充的。在启动完成后,PHP将在脚本执行期间再次NOT触摸它们(除了$_SESSION,正如Khez在下面指出的)。基本上,设定它+忘记它。所有影响超全局变量的php函数(特别是set_cookie())都不会再触及这些数组,它不是"异步"的。它完全电离了。cookie唯一出现在$_COOKIE中的情况是,它出现在导致脚本执行的请求的HTTP头文件中。
你可以重载setcookie来做你想做的事情,但通常你不应该这样做。$_COOKIE表示客户端发出请求时的状态。如果开始向$_COOKIE写入新数据,就会丢失客户端的状态。
答案很简单,只需编写您自己的cookie设置函数,该函数既可以设置HTTP标头,也可以设置该页面加载时使用的变量。
正如我在这个答案中概述的那样,您可以通过直接写入$_COOKIE
数组来实现这一点,但是这会让您陷入一点混乱,因为它很容易忘记什么是"真正的"cookie,以及您已经覆盖的内容。
我个人更喜欢的方法是为获取和设置cookie编写一组自定义函数,它在初始化时读取$_COOKIE
,然后从那时起跟踪事物本身。有点像这样(不是完整的实现):
class Cookie_Handler
{
private static $initialised=false;
private static $current_cookies;
public static function initialise()
{
self::$current_cookies = $_COOKIE;
self::$initialised = true;
}
public static function set_cookie($cookie_name, $cookie_value)
{
if ( ! self::$initialised )
{
self::initialise();
}
setcookie($cookie_name, $cookie_value, time() + (1000 * 120),'/','',false,false);
self::$current_cookies[$cookie_name] = $cookie_value;
}
public static function get_cookie($cookie_name)
{
if ( ! self::$initialised )
{
self::initialise();
}
return self::$current_cookies[$cookie_name];
}
}
只需在数组$_COOKIE
中手动赋值(如$_COOKIE['mycookie']=$_GET['supahCookie']
),同时调用setcookie
。
编辑:
正如在其他答案中所指出的,可能不建议"违反"请求状态数组,并且判断cookie是否确实设置是不可靠的,因为浏览器可以简单地拒绝它。我的第一个解决方案旨在允许您在专注于真实事物而不是实现细节(例如检测浏览器拒绝cookie)的同时玩弄cookie。
我仍然可以看到至少有两种方法来处理它,而不需要整个页面重新加载,但是都需要用户的浏览器发送第二个请求(这已经向你解释了了解客户端cookie的真实状态是必要的)。
(坏的方式)你可以使用
IFrame
。将它的边框、边距和内边距设置为0,然后手动调整它的高度,这样你就可以让它看起来像另一个段落——假设你想要它。这将使您创建另一个页面,只返回一个句子-无论访问者是否指定cookie设置;并设置IFrame的src
属性指向新页面我建议使用
XMLHttpRequest
object。这样,您仍然需要创建另一个页面,该页面将返回一个句子(无论浏览器是否发送cookie),XMLHttpRequest
将接收并处理JavaScript
。此解决方案的代码片段如下:
假设您的页面上有<span id="cookie_state"></span>
,您可以在<script></script>
右alter span的定义中放置以下代码:
var xhttp = new XMLHttpRequest;
xhttp.onreadystatechange=function()
{
if (xhttp.readyState==4 && xhttp.status==200)
{
document.getElementById("cookie_state").innerHTML=xhttp.responseText;
}
}
xhttp.open("GET","cookie_info.php",true);
xhttp.send();
当然,如果你只是想在脚本中使用新的cookie传递它,你可以先检查天气或是否cookie设置,如果它已经被分配给一些变量,如果没有-创建它,然后分配给变量,不需要每次看$_COOKIE数组的值