setcookie()之后立即访问$ _COOKIE


79

在PHP中$_COOKIE调用setcookie()函数后,我试图立即访问cookie的值(使用)。当我这样做时,$_COOKIE['uname']没有设置。为什么?

但是请注意,$_COOKIE['uname']在下次执行脚本时(例如在刷新页面后)将按预期进行设置。

setcookie('uname', $uname, time() + 60 * 30);
echo "Cookie value: " . $_COOKIE['uname'];

不幸的是,这里的答案没有提供解决方案,也没有建议不好的解决方法,甚至不能接受,请参阅stackoverflow.com/questions/3230133#34465594
witrin 2015年

@witrin您提供的链接似乎重定向到相同的问/答。
Trainoasis '16

这是不可能的。您必须通过$_COOKIE自己设置相应的条目或立即执行重定向(到同一页面)来“伪造”它。
caw

Answers:


36

$_COOKIE由于网页的无状态性质,因此在页面加载时设置。如果要立即访问,则可以设置$_COOKIE['uname']自己或使用中间变量。

例如:

if (isset($_COOKIE['uname'])) {
    // get data from cookie for local use
    $uname = $_COOKIE['uname'];
}
else {
    // set cookie, local $uname already set
    setcookie('uname', $uname, time() + 1800);  
}

20
这不会使cookie在刷新页面之前就可访问...参见Mark Ba​​ker的答案:)
探路者

这不是真的。我已经根据OP的代码做出了他们$uname在脚本中使用的假设。而Mark Ba​​ker$_COOKIE['uname']直接使用。
詹森·麦克雷里

1
对不起,我说错了。就我而言,这是针对异步脚本的,设置$ _COOKIE并没有实际设置cookie并将其发送回浏览器(我也需要cookie),它只是使其在我的脚本中可用。您还需要使用setcookie(),Mark Ba​​ker的答案就是这样做的。另外,他的代码更短,对来自Google搜索的人更有用。
探路者

我用setcookie()。该答案可能无法满足您的确切需求。但这并没有。OP和SO已发现此答案很有用。
杰森·麦克雷里

2
我不明白为什么这个答案被标记为“答案”。它没有说明如何直接使用cookie,并且提供的代码就像发布的相同OP。setcookie()在该代码之后,将无法访问$_COOKIE['uname']
Isthar,2015年

151

直到将响应发送回客户端之前,才会设置cookie,并且直到之后客户端的下一个请求才在您的PHP中使用该cookie。

但是,在脚本中设置Cookie时,您可以执行以下操作:

setcookie('uname', $uname, time()+60*30);
$_COOKIE['uname'] = $uname;

2
非常简单的解决方案。谢谢!
dawoodman71

1
好东西。我不知道第二行如何设置未传递的到期时间?
martinedwards

2
@martinedwards第二行没有设置任何到期时间....它设置为请求的持续时间;在请求期间,存在与来自浏览器的请求一起传入的Cookie值完全相同的方式
Mark Ba​​ker

@MarkBaker简单解决方案!非常感谢
Shan

你的意思是说。要访问cookie值,需要两次访问Page(php文件)。第一次设置cookie,第二次访问设置的cookie。正确?
Pratik 2015年

31

如果您要在调用cookie后立即访问cookie的值setcookie(),则不能使用$_COOKIE原因在于协议的性质(请参阅https://tools.ietf.org/html/rfc6265)。当您使用setcookie()它时,它定义了一个Cookie和其他HTTP标头一起发送到客户端(请参阅http://php.net/manual/en/function.setcookie.php)。但是$_COOKIE另一方面,它包含从客户端http://php.net/manual/en/reserved.variables.cookies.php)通过HTTP Cookies传递到当前脚本的变量。

$_COOKIE致电后进行更改时setcookie()(如此处建议的一些答案),它不再仅包含来自客户端的Cookies。这可能会干扰您的应用程序中使用的第三方代码所做的假设,并可能导致有害的站点影响。因此,通常这不是一个好习惯,并且仅当您的调用setcookie()是您自己的代码的一部分时才是一种选择。

setcookie()在同一请求中使用干净透明的方法来获取值集的方法是使用headers_list()(请参阅http://php.net/manual/en/function.headers-list.php

function getcookie($name) {
    $cookies = [];
    $headers = headers_list();
    // see http://tools.ietf.org/html/rfc6265#section-4.1.1
    foreach($headers as $header) {
        if (strpos($header, 'Set-Cookie: ') === 0) {
            $value = str_replace('&', urlencode('&'), substr($header, 12));
            parse_str(current(explode(';', $value, 1)), $pair);
            $cookies = array_merge_recursive($cookies, $pair);
        }
    }
    return $cookies[$name];
}
// [...]
setcookie('uname', $uname, time() + 60 * 30);
echo "Cookie value: " . getcookie('uname');

但是请注意,这在PHP CLI(例如PHPUnit)中不起作用。在这种情况下,您可以使用XDebug等第三方扩展(请参阅http://xdebug.org/docs/all_functions#xdebug_get_headers)。


6
这里只有一个真正的解决方案。干净,没有修改可能包含setcookie的第三者代码。
迈克尔

1
我不确定操作人员为何投票赞成其他解决方案,但这实际上是对我有帮助的正确解决方案。
ChrisP777 '18

这100%是对生产环境可行的唯一答案。伟大的解决方案@witrin
Skidadon

我不知道为什么,但是$ limit参数对explode()我不起作用,仅返回一个数组元素,其中的整个字符串位于其中:ideone.com/7SnV9y
NaturalBornCamper

5

如果您需要立即使用cookie变量,则必须自己设置。在加载另一页时,将通过setcookie方法设置实际的cookie。

setcookie('name', $value, time()+60*30);
$_COOKIE ['name'] = $value;

1

我们可以使用AJAX调用来做到这一点。

如果要在按钮上单击创建cookie,则首先创建一个用于创建cookie的AJAX调用,然后成功进行第一个AJAX调用,我们可以调用另一个AJAX来获取cookie。

    function saveCookie() {
            var base_url = $('#base_url').val();
            var url = base_url + '/index/cookie';
            $.ajax({
                'url': url,
                'type': 'POST',
                'success': function (data) {
                    if (data) {
                        var url = base_url + '/index/get_cookie';
                        $.ajax({
                            'url': url,
                            'type': 'POST',
                            'success': function (response) {
                                var container = $('#show');
                                if (response) {
                                    container.html(response);
                                }
                            }
                        });
                    }
                }
            });
        }

    <button type="button" onclick="saveCookie()">Save Cookie</button>
    <div id="show"></div>

要知道,即使意图很好,OP也只需要一个PHP答案。:)也许这就是为什么您要投票,但我没有投票给您。
马克西玛Alekz

赞成,因为这也是应该考虑的一种方法!
Dhruv Thakkar

1

我有一个类似的问题,其中我使用了包含文件中的一个函数,并用一个既返回cookie值又设置cookie的函数解决了它。

function setCookie($input) {
  setcookie('uname', $input, time() + 60 * 30);
  return $input;
}

if(!isset($_COOKIE['uname'])) {
    $uname  = setCookie($whatever);
} else {
    $uname = $_COOKIE['uname'];
}

echo "Cookie value: " . $uname;

-1

使用ob_start()ob_flush(),您可以将cookie发送到客户端,并在相同的运行时检索它。试试这个:

ob_start();
setcookie('uname', $uname, time() + 60 * 30);
ob_flush();
echo "Cookie value: " . $_COOKIE['uname'];

这似乎不起作用(带有nginx的PHP 5.4)。你能扩大吗?
Paul DelRe 2014年

-1

setcookie()当Web浏览器首次请求页面时,脚本功能将运行,在这种情况下为重新加载。此cookie存储在用户浏览器中,在下一个请求或您的下一次重新加载之前,该cookie在服务器上运行的脚本不可用。

在下一个请求时,浏览器将该cookie发送到服务器,该数组$_COOKIE将具有您最初设置的值,并且浏览器将在第二个请求后发回。


-3

我在创建Cookie的同时设置了一个常量

define('CONSTANT', true);
return setcookie('cookiename', 'cookie value goes here', time() + 60 * 60 * 24 * 30, '/');

然后,我可以通过以下方式立即执行操作:

if(isset($_COOKIE['cookiename']) || $_COOKIE['cookiename'] || defined('CONSTANT') && CONSTANT)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.