0

这是一个代码示例:

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']; 

我是不是又在这里发明了一个轮子?

有没有人有其他更优雅的解决方案?

4

3 回答 3

2

$_COOKIE,其余的超全局变量是作为 PHP 启动例程的一部分填充的。启动完成后,在脚本执行期间,PHP 将不再接触它们($_SESSION 除外,正如Khez指出的那样)。设置它+忘记它,基本上。影响超全局变量(特别是 set_cookie())的 php 函数都不会再次接触这些数组,它不是“异步的”。它是完全分离的。cookie 出现在 $_COOKIE 中的唯一时间是它出现在导致脚本执行的请求的 HTTP 标头中。

你可以重载 setcookie 来做你想做的事,但通常你不应该这样做。$_COOKIE 表示客户端发出请求时的状态。如果您开始向 $_COOKIE 写入新数据,您将失去客户端的状态。

于 2013-05-02T21:00:35.507 回答
1

只需$_COOKIE手动(如$_COOKIE['mycookie']=$_GET['supahCookie'])在数组中分配值以及调用setcookie.


编辑: 正如其他答案中所述,可能不建议“违反”请求状态数组,并且判断是否确实设置了 cookie是不可靠的,因为浏览器可能会简单地拒绝它。我的第一个解决方案旨在让您在专注于实际事物而不是实现细节的同时使用 cookie(例如检测拒绝 cookie 的浏览器)。

我仍然可以看到至少有两种方法可以在不重新加载整个页面的情况下处理它,但是两者都需要用户的浏览器发送第二个请求(已经向您解释过这是了解客户端 cookie 的真实状态所必需的)。

  1. (不好的方式)你可以使用IFrame. 将它的边框、边距和内边距设置为 0,然后手动调整它的高度可以让它看起来像另一个段落——假设你想要它。这将让您创建另一个只返回一个句子的页面 - 无论访问者是否指定了 cookie 集;并将 IFrame 的src属性设置为指向新页面。

  2. 我建议使用XMLHttpRequestobject。这样,您仍然必须创建另一个页面,该页面将返回一个句子(无论浏览器是否发送 cookie),XMLHttpRequest它将接收和处理JavaScript. 此解决方案的代码片段如下。

假设您<span id="cookie_state"></span>的页面上有某处,您可以将以下代码放在<script></script>正确的更改跨度的定义中:

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 数组中的值时都需要查看。

于 2013-05-02T20:59:04.737 回答
1

答案就是编写您自己的 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];
    }
}
于 2013-05-02T21:09:10.463 回答