Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are my cookies not setting?

Tags:

php

cookies

I have the following PHP function:

function validateUser($username){     session_regenerate_id ();      $_SESSION['valid'] = 1;     $_SESSION['username'] = $username;     setcookie('username2',$username,time()+60*60*24*365);     header("Location: ../new.php"); } 

And then I fetch the cookie:

echo $_COOKIE['username2']; exit();

(I only put exit() for debugging purposes)

Only problem, it's coming out blank. Any ideas?

UPDATE: This is how the function is called:

    if(mysql_num_rows($queryreg) != 0){     $row = mysql_fetch_array($queryreg,MYSQL_ASSOC);     $hash = hash('sha256', $row['salt'] . hash('sha256', $password));     if($hash == $row['password']) {         if($row['confirm'] == 1){             if(isset($remember)){                 setcookie('username',$username,time()+60*60*24*365);                 setcookie('password',$password,time()+60*60*24*365);             } else {                 setcookie('username','',time()-3600);                 setcookie('password','',time()-3600);             }             validateUser($username); 

I didn't include all the if() statements to save some space.

like image 803
Jason Avatar asked Aug 07 '11 04:08

Jason


People also ask

How do I know if my cookies are set?

Use the isset() function upon the superglobal $_COOKIE variable to check if a cookie is set.

Are cookies automatically set?

Cookies are usually set by a web-server using the response Set-Cookie HTTP-header. Then, the browser automatically adds them to (almost) every request to the same domain using the Cookie HTTP-header.

Does set cookie overwrite?

A cookie can only be overwritten (or deleted) by a subsequent cookie exactly matching the name, path and domain of the original cookie. Even though a cookie with domain “.


2 Answers

try adding the path = /, so that the cookie works for the whole site not just the current directory (that has caught me out before)

example

setcookie('password',$password,time()+60*60*24*365, '/');  

also make sure the cookie is the first thing being output as advised in the php manual (this has caught me out before too)

Like other headers, cookies must be sent before any output from your script (this is a protocol restriction).

like image 146
bumperbox Avatar answered Sep 21 '22 21:09

bumperbox


Why you are having this problem

The problem comes from the fact that setcookie() doesn't set the cookies immediately, it sends the headers so the browser sets the cookies. This means that, for the current page load, setcookie() will no generate any $_COOKIE.

When the browser later on requests a page, it sends the cookies in the headers so the PHP can retrieve them in the form of $_COOKIE.

Simple, old solution

About solutions, the obvious one:

setcookie('username',$username,time()+60*60*24*365); // 'Force' the cookie to exists $_COOKIE['username'] = $username; 

A better solution

I created a class, Cookie, that addresses the problems that setcookie() and $_COOKIE share:

// Class that abstracts both the $_COOKIE and setcookie() class Cookie   {   // The array that stores the cookie   protected $data = array();    // Expiration time from now   protected $expire;   // Domain for the website   protected $domain;    // Default expiration is 28 days (28 * 3600 * 24 = 2419200).   // Parameters:   //   $cookie: $_COOKIE variable   //   $expire: expiration time for the cookie in seconds   //   $domain: domain for the application `example.com`, `test.com`   public function __construct($cookie, $expire = 2419200, $domain = null)     {     // Set up the data of this cookie     $this->data = $cookie;      $this->expire = $expire;      if ($domain)       $this->domain = $domain;     else       {       $this->domain =          isset($_SERVER['HTTP_X_FORWARDED_HOST']) ?         $_SERVER['HTTP_X_FORWARDED_HOST'] :         isset($_SERVER['HTTP_HOST']) ?           $_SERVER['HTTP_HOST'] :           $_SERVER['SERVER_NAME'];       }     }    public function __get($name)     {     return (isset($this->data[$name])) ?       $this->data[$name] :       "";     }    public function __set($name, $value = null)     {     // Check whether the headers are already sent or not     if (headers_sent())       throw new Exception("Can't change cookie " . $name . " after sending headers.");      // Delete the cookie     if (!$value)       {       setcookie($name, null, time() - 10, '/', '.' . $this->domain, false, true);       unset($this->data[$name]);       unset($_COOKIE[$name]);       }      else       {       // Set the actual cookie       setcookie($name, $value, time() + $this->expire, '/', $this->domain, false, true);       $this->data[$name] = $value;       $_COOKIE[$name] = $value;       }     }   } 

Then you can use it like this:

$Cookie = new Cookie($_COOKIE); $User = $Cookie->user; $LastVisit = $Cookie->last; $Cookie->last = time(); 

And of course, you have to pass it around. Much better than having globals.

like image 36
Francisco Presencia Avatar answered Sep 22 '22 21:09

Francisco Presencia