【问题标题】:Accessing $_COOKIE immediately after setcookie()在 setcookie() 之后立即访问 $_COOKIE
【发布时间】:2011-03-14 21:28:06
【问题描述】:

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

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

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

【问题讨论】:

  • 不幸的是,这里的答案并没有提供解决方案或建议错误的解决方法,即使是已接受的,请参阅stackoverflow.com/questions/3230133#34465594
  • @witrin 您提供的链接似乎重定向到同一个问题。
  • 这是不可能的。您必须“伪造”它,要么自己设置$_COOKIE 中的相应条目,要么立即执行重定向(到同一页面)。

标签: php cookies


【解决方案1】:

$_COOKIE 在页面加载时设置,这是由于 Web 的无状态特性。如果您想立即访问,您可以自己设置$_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);  
}

【讨论】:

  • 这不会在页面刷新之前使 cookie 可访问...请参阅 Mark Ba​​ker 的答案进一步:)
  • 这不是真的。根据 OP 的代码,我假设他们在脚本中使用 $uname。而马克贝克直接使用$_COOKIE['uname']
  • 对不起,我说的有点不对。出于我的目的,即用于异步脚本,设置 $_COOKIE 并没有实际设置 cookie 并将其发送回浏览器(我也需要 cookie),它只是使它在我的脚本中可用。您也需要使用 setcookie() ,马克贝克的回答就是这样做的。此外,他的代码更短,对通过谷歌搜索来到这里的人更有用。
  • 我使用setcookie()。此答案可能无法满足您的确切需求。但这并不意味着它错误。 OP 和 SO 发现这个答案很有用。
  • 我不明白为什么这个答案被标记为“答案”。它没有解释如何直接使用cookie,并且提供的代码就像发布的同一个OP。在该代码中的setcookie() 之后,无法访问$_COOKIE['uname']
【解决方案2】:

在将响应发送回客户端之前不会设置 cookie,并且在客户端发出下一个请求之前在您的 PHP 中不可用。

但是,当您在脚本中设置 cookie 时,您可以:

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

【讨论】:

  • 非常简单的解决方案。谢谢!
  • 好东西。我想知道第二行没有传入时如何设置到期时间?
  • @martinedwards 第二行没有设置任何到期时间....它设置为请求的持续时间;与来自浏览器的请求一起传入的 cookie 值在请求期间存在的方式完全相同
  • @MarkBaker 简单解决方案!!非常感谢
  • 你的意思是说。要访问 cookie 值,页面(php 文件)需要访问两次。第一次设置cookie,第二次访问设置的cookie。对吗?
【解决方案3】:

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

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

【讨论】:

  • 这似乎不起作用(PHP 5.4 w/ nginx)。可以扩展一下吗?
【解决方案4】:

您的脚本的setcookie() 函数在网络浏览器第一次请求页面时运行,在您的情况下是重新加载。此 cookie 存储在用户浏览器中,直到下一次请求或您的情况下一次重新加载之前,您在服务器上运行的脚本才能使用此 cookie。

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

【讨论】:

    【解决方案5】:

    我在创建 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)
    

    【讨论】:

      【解决方案6】:

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

      如果我们想在按钮单击时创建 cookie,那么首先创建一个 AJAX 调用来创建 cookie,然后第一次 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 的答案。 :) 也许这就是你投反对票的原因,我没有反对你。
      • 赞成,因为这也是应该考虑的一种方法!
      【解决方案7】:

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

      当您在调用setcookie() 后更改$_COOKIE - 就像这里推荐的一些答案一样 - 它不再只包含来自客户端的Cookie。这可能会干扰在您的应用程序中使用的第三方代码中所做的假设,并可能导致不需要的站点效果。所以一般来说,这不是一个好的做法,只有当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)。

      【讨论】:

      • 这里只有一个真正的解决方案。干净,无需修改可能包含 setcookie 的 3rd 方代码。
      • 我不确定为什么操作员投票支持其他解决方案,但这是真正帮助我的正确解决方案。
      • 这 100% 是唯一适用于生产环境的答案。很好的解决方案@witrin
      • 我不知道为什么,但是explode() 上的 $limit 参数对我不起作用,只返回一个包含整个字符串的数组元素:ideone.com/7SnV9y
      【解决方案8】:

      如果您立即需要它,您必须自己设置 cookie 变量,当您加载另一个页面时,真正的 cookie 将作为 setcookie 方法的结果设置。

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

      【讨论】:

        【解决方案9】:

        我有一个类似的问题,我使用了包含文件中的一个函数,并用一个既返回 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;
        

        【讨论】:

          猜你喜欢
          • 2017-03-16
          • 2014-12-22
          • 2018-12-07
          • 1970-01-01
          • 2012-01-22
          • 2013-12-27
          • 1970-01-01
          相关资源
          最近更新 更多