92

I'm trying to access a cookie's value (using $_COOKIE) immediately after calling the setcookie() function in PHP. When I do so, $_COOKIE['uname'] isn't set. Why?

Note, however, that $_COOKIE['uname'] is set as expected upon the next execution of the script, such as after a page refresh.

setcookie('uname', $uname, time() + 60 * 30);
echo "Cookie value: " . $_COOKIE['uname'];
outis
  • 75,655
  • 22
  • 151
  • 221
heapzero
  • 1,413
  • 2
  • 13
  • 18
  • Unfortunately the answers here doesn't offer a solution or suggesting bad workarounds even the accepted, see http://stackoverflow.com/questions/3230133#34465594. – witrin Dec 26 '15 at 10:58
  • @witrin your provided link seems to redirect to this same q/a. – trainoasis Mar 11 '16 at 07:25
  • 2
    This is not possible. You have to "fake" it, either by setting the corresponding entries in `$_COOKIE` yourself or by performing a redirect (to the same page) immediately. – caw Jul 12 '16 at 23:57

9 Answers9

164

The cookie isn't set until the response is sent back to the client, and isn't available in your PHP until the next request from the client after that.

However, when you set the cookie in your script, you can do:

setcookie('uname', $uname, time()+60*30);
$_COOKIE['uname'] = $uname;
Mark Baker
  • 209,507
  • 32
  • 346
  • 385
40

$_COOKIE is set when the page loads, due to the stateless nature of the web. If you want immediate access, you can set $_COOKIE['uname'] yourself or use an intermediate variable.

For example:

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);  
}
Jason McCreary
  • 71,546
  • 23
  • 135
  • 174
  • 24
    this does not make the cookie accessible before a page refresh... see Mark Baker's answer further down for that :) – pathfinder Mar 28 '13 at 02:14
  • That's not true. I've made the assumption, based off the OP's code, that they use `$uname` in their script. Whereas Mark Baker uses `$_COOKIE['uname']` directly. – Jason McCreary Mar 28 '13 at 14:13
  • 1
    I'm sorry I said it a bit wrong. For my purposes, which are for an asynchronous script, setting $_COOKIE did not actually set the cookie and send it back to the browser (I needed the cookie there too), it only made it available in my script. You need to use setcookie() too, which Mark Baker's answer does. Plus his code is a lot shorter and more useful to people coming here from a google search. – pathfinder Mar 28 '13 at 18:06
  • I use `setcookie()`. This answer may not meet your exact needs. But that doesn't make it *wrong*. The OP and SO have found this answer to be useful. – Jason McCreary Mar 29 '13 at 17:54
  • You mean to say. to access cookie value , Page(php file) needs to be accessed twice. 1st time to set cookie, and 2nd time to access the set cookie. Correct? – Pratik Joshi Dec 09 '15 at 04:36
  • 2
    I don't understand why this answer is marked as "the answer". It doesn't explains how to use the cookie directly, and the code provided is like the same OP posted. After `setcookie()` in that code it is not possible to access `$_COOKIE['uname']` – Isthar Jan 26 '17 at 15:51
38

If you want to access a cookie's value immediately after calling the setcookie() you can't use $_COOKIE. The reason for this is in the nature of the protocol (see https://www.rfc-editor.org/rfc/rfc6265). When you use setcookie() it defines a Cookie to be sent along with the rest of the HTTP headers to the client (see http://php.net/manual/en/function.setcookie.php). But $_COOKIE on the other hand contains variables passed to the current script via HTTP Cookies from the client (http://php.net/manual/en/reserved.variables.cookies.php).

When you change $_COOKIE after calling setcookie() - like some answers here recommend - it doesn't contain only the Cookies from the client any more. This could interferer with assumptions made in third party code used in your application and may result in unwanted site effects. So in general it's not good practice and it's only an option when the calls of setcookie() are part of your own code.

A clean and transparent way to get a value set with setcookie() within the same request is to use headers_list() (see 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');

But notice this won't work in PHP CLI (e.g. PHPUnit). In such a case you could use third party extensions like XDebug (see http://xdebug.org/docs/all_functions#xdebug_get_headers).

Community
  • 1
  • 1
witrin
  • 3,701
  • 1
  • 24
  • 49
  • 7
    Only one real solution here. Clean, without modifications of 3rd party code that could contain setcookie. – Michael Sep 20 '16 at 15:41
  • 1
    I am not sure why the op voted for the other solution, but this is the correct solution that actually helped me. – ChrisP777 Mar 19 '18 at 17:28
  • 1
    This 100% the only answer that is viable for a production environment. Great solution @witrin – skidadon Apr 29 '20 at 00:23
  • 1
    I don't know why, but the $limit parameter on `explode()` does't work for me, just returns one array element with the whole string inside: https://ideone.com/7SnV9y – NaturalBornCamper Jun 02 '20 at 14:19
8

You have to set the cookie variable by yourself if you need it immediately, by the time you load another page the real cookie would have been set as a result of the setcookie method.

setcookie('name', $value, time()+60*30);
$_COOKIE ['name'] = $value;
Joshua
  • 818
  • 11
  • 12
4

We can do this using AJAX calling.

If we want to create cookies on button click so first create a AJAX call for creating cookies then the success of first AJAX calling we can call another AJAX for getting the cookies.

    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>
1

I had a similar problem where i used a function from a included file and solved it with a function that both returns the value of the cookie and sets the 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;
0

Using ob_start() and ob_flush() you can send the cookie to client and retrieve it in the same run time. Try this:

ob_start();
setcookie('uname', $uname, time() + 60 * 30);
ob_flush();
echo "Cookie value: " . $_COOKIE['uname'];
Will Soares
  • 455
  • 4
  • 5
0

Your script's setcookie() function runs when the web browser requests the page for the first time, in your case the reload. This cookie is stored in the users browser and isn't available to your script running on the server until the next request, or in your case the next reload.

Upon the next request the browser sends that cookie to the server and the array $_COOKIE will have the value that you initially set and the browser sent back upon the second request.

Robert
  • 10,126
  • 19
  • 78
  • 130
-2

I set a constant at the same time the cookie was created

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

I can then immediately do something by:

if(isset($_COOKIE['cookiename']) || $_COOKIE['cookiename'] || defined('CONSTANT') && CONSTANT)
virtualLast
  • 573
  • 1
  • 5
  • 19