2013-05-02 88 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