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));
}

うーん..もう1つ、少し厄介なものがあります。

$foo = empty($_GET['supahCookie'])?(empty($_COOKIE['myCookie'])?'Empty! :(':$_COOKIE['myCookie']):$_GET['supahCookie']; 

ここでまた車輪を発明しているのでしょうか?

他のよりエレガントなソリューションはありますか?

4

3 に答える 3

2

いいえ$_COOKIE、残りのスーパーグローバルは、PHP のスタートアップ ルーチンの一部として読み込まれます。起動が完了すると、スクリプトの実行中、PHP はそれらに二度と触れません(以下で Khez が指摘しているように、$_SESSION を除く)。基本的に、設定して忘れてください。スーパーグローバル (特に set_cookie()) に影響を与える php 関数は、これらの配列に再び触れることはありません。これは「非同期」ではありません。完全に切り離されています。Cookie が $_COOKIE に表示されるのは、スクリプトが実行される原因となったリクエストの HTTP ヘッダーに Cookie が存在する場合のみです。

必要なことを行うために setcookie をオーバーロードできますが、通常はそうすべきではありません。$_COOKIE は、リクエストを行ったときのクライアントの状態を表します。$_COOKIE に新しいデータを書き始めると、クライアントの状態が失われます。

于 2013-05-02T21:00:35.507 に答える
1

答えは、HTTP ヘッダーを設定し、そのページの読み込みで使用する変数を設定する独自の Cookie 設定関数を作成することです。

この回答で概説したように、配列に直接書き込むことでこれを行うことができ$_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 に答える
1

を呼び出すとともに、配列に値を$_COOKIE手動で( のように)割り当てるだけです。$_COOKIE['mycookie']=$_GET['supahCookie']setcookie


編集: 他の回答で述べたように、リクエスト状態配列に「違反」することはお勧めできません。また、ブラウザが単純に拒否する可能性があるため、Cookie が実際に設定されているかどうかを判断することは信頼できません。私の最初のソリューションは、実装の詳細 (Cookie を拒否するブラウザーの検出など) ではなく、実際のものに集中しながら、Cookie をいじることができるようにすることを目的としていました。

ページ全体をリロードせずに対処する方法が少なくとも 2 つありますが、どちらもユーザーのブラウザに 2 番目のリクエストを送信する必要があります (これは、クライアント Cookie の実際の状態を知るために必要であることが既に説明されています)。

  1. (悪い方法) を使用できますIFrame。ボーダー、マージン、パディングを 0 に設定してから、高さを手動で調整すると、別の段落のように見えるようになります。これにより、訪問者が Cookie セットを指定したかどうかに関係なく、1 つの文のみを返す別のページを作成する必要があります。src新しいページを指すようにIFrame の属性を設定します。

  2. XMLHttpRequestobjectの使用をお勧めします。. _ 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 に答える