2013-05-02 82 views
0

这里是一个代码示例:PHP绕过setcookie()的'pseudo asynchrony';功能

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

我在这里发明了一个轮子吗?

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

+0

'的setcookie( '的myCookie',$ _ GET [ 'supahCookie'],时间()+ 3600 * 24 * 31); $ _ COOKIE [” myCookie'] = $ _ GET ['supahCookie'];' – Khez 2013-05-02 21:01:51

回答

1

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


编辑: 在其他的答案提到的,可以不推荐“违反”请求状态阵列,并且它是不可靠的来判断是否饼干确实已经设置,因为浏览器可以简单地拒绝它。我的第一个解决方案旨在让您在专注于真实情况而不是实现细节(例如检测浏览器拒绝cookie等)的情况下玩弄cookies。

我仍然可以看到至少有两种方式来处理它,而无需全部页面重新加载,但都要求用户的浏览器发送第二个请求(已经向您解释了这是为了了解客户端cookie的真实状态所必需的)。

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

  2. 我会推荐使用XMLHttpRequest对象。这样您仍然必须创建另一个页面,它将返回一个句子(不管浏览器是否发送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数组中的值。

+0

好的! :)比重定向更冷却 – rinchik 2013-05-02 21:02:18

+0

编辑,增加了真实的方式。 – Cthulhu 2013-05-03 05:36:09

2

编号$_COOKIE其余超级全局变量是PHP的启动例程的一部分。启动完成后,PHP将不是在脚本执行期间再次触摸它们(除了$ _SESSION,正如Khez指出的那样)。设置它+基本上忘记它。没有任何影响超级全局变量的php函数(特别是set_cookie())再次触及这些数组,它不是“异步”的。它完全失去了联系。 Cookie出现在$ _COOKIE中的唯一时间是它出现在导致脚本执行的请求的HTTP标头中。

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

+0

我完全同意你的看法,期待你所说的部分“PHP将**不再**再次触摸它们”。这不适用于** $ _ SESSION **。无论何时调用* session_start *,会话变量总是被重新填充。 – Khez 2013-05-02 21:03:37

+0

啊是的。真的够了。 – 2013-05-02 21:04:56

+0

所以'$ _COOKIE ['myCookie'] = $ _ GET ['supahCookie'];'是不是一个推荐的做法? – rinchik 2013-05-02 21:06:22

1

答案只是编写自己的cookie设置函数,它既设置HTTP标头,又设置一个用于该页面加载的变量。

正如我概括in this answer,你可以通过直接写入$_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]; 
    } 
} 
+0

omg它的巨大! ind似乎是它的一个bugger版本'$ _COOKIE ['myCookie'] = $ _ GET ['supahCookie'];' – rinchik 2013-05-02 21:26:45

+0

哈哈,真的。当然,你可以更多地处理cookie的*为*,而不是一般的cookie(也包括'$ _GET'逻辑)。其目的是让代码的其余部分不太关心读取和写入值的细节,更关心他们试图使用这些值。 – IMSoP 2013-05-02 21:42:49