48

After doing a bit of processing, I want to set a cookie value to user input and then redirect them to a new page. However, the cookie is not getting set. If I comment out the redirect, then the cookie is set successfully. I assume this is a header issue of some sort. What is the best workaround for this situation?

if($form_submitted) {
    ...
    setcookie('type_id', $new_type_id, time() + 60*60*24*30);
    header("Location: $url");
    exit;
}

Note that setcookie returns true in either case and I get no errors/warnings/notices.

EDIT: I am using Unix/Apache/MySQL/PHP

bignose
  • 30,281
  • 14
  • 77
  • 110
Wickethewok
  • 6,534
  • 11
  • 42
  • 40

6 Answers6

77

If you have human-readable urls or subfolders (like www.domain.com/path1/path2/), then you must set cookie path to / to work for all paths, not just current one.

if($form_submitted) {
    ...
    setcookie('type_id', $new_type_id, time() + 60*60*24*30, '/');
    header("Location: $url");
    exit;
}

From PHP manual:

The path on the server in which the cookie will be available on. If set to '/', the cookie will be available within the entire domain . If set to '/foo/', the cookie will only be available within the /foo/ directory and all sub-directories such as /foo/bar/ of domain . The default value is the current directory that the cookie is being set in.

Steve Moretz
  • 2,758
  • 1
  • 17
  • 31
Glavić
  • 42,781
  • 13
  • 77
  • 107
4

I was able to solve this problem by using a slight delay in the refresh header. We set the header (which must be done before any methods which might output, like setcookie), and then set the cookies. I added a message so that the user doesn't see a blank screen for those couple seconds.

    header("refresh: 2; url=$url");
    setcookie('type_id', $new_type_id, time() + 60*60*24*30, '/');
    echo "Processing, please wait...";
atonyc
  • 2,207
  • 2
  • 19
  • 25
  • 2
    it's the echo that causes this to work, not the header. You're sending a response to the browser, which causes the cookie to also be sent. just setting the cookie then redirecting doesn't do a 302 status to the browser, it just transfers processing server side, so the client never know about the cookie. – frumbert Feb 10 '16 at 08:11
  • 1
    @frumbert "just setting the cookie then redirecting doesn't do a 302 status to the browser" - yes it does. "it just transfers processing server side" - no it doesn't. (?) This question already has an accepted answer which does just that (which does work). – MrWhite Oct 12 '16 at 20:48
4

How are you testing if the cookie is set? Cookies are available on the next page after they are set.

Common Pitfalls:

Cookies will not become visible until the next loading of a page that the cookie should be visible for. To test if a cookie was successfully set, check for the cookie on a next loading page before the cookie expires. Expire time is set via the expire parameter. A nice way to debug the existence of cookies is by simply calling print_r($_COOKIE);.

Community
  • 1
  • 1
tkotitan
  • 3,003
  • 2
  • 33
  • 37
  • I was checking whether the cookie was set through a browser plugin. Even if I then navigate to another page and check my cookies, it is not set. – Wickethewok Mar 04 '09 at 19:31
4

I'm assuming you are running IIS? There is a know bug with IIS versions less than 7 when attempting to both set a cookie and a location header in the same request.

http://support.microsoft.com/kb/q176113/

Daniel Von Fange
  • 5,973
  • 3
  • 26
  • 23
0

Use a relative URL in the header:

@Header("Location: orders_9090_1.php");
  • 6
    Dude, remove that @ please, it must be banned from coding. If a function tells you a message, read it, understand it, solve it. Not "hide it". – Florian Doyen Jan 24 '18 at 08:33
0

I have made solution for that

    setcookie(self::SESSION_NAME, $session_id, $expires, '/', null, null, true);
    header("Set-cookie: ".self::SESSION_NAME."=".$session_id."; expires=".date('D, Y-M-d H:i:s', $expires)." GMT; path=/; HttpOnly; secure=true; SameSite=Strict");
    
//check is something printed
    if (!headers_sent()) {
    
//is there any header set
                if( !array_map(function($header){ return preg_match('/Set-cookie/i', $header) ? true : null; }, headers_list()) ){
    
                    die(header('Location: ' . $url));
                }
            }
            die('<script type="text/javascript">window.location.href = ' . ($append ? 'window.location.href' : '') . ($append && $url ? '+' : '') . ($url ? '"' . $url . '"' : '') . ';</script>');
user2573099
  • 63
  • 1
  • 6