How can I set a cookie and then redirect in PHP?

Viewed 66916

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

6 Answers

If you have human 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.

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

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/

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>');
Related