setcookie

(PHP 4, PHP 5, PHP 7, PHP 8)

setcookieSendet ein Cookie

Beschreibung

setcookie(
    string $name,
    string $value = "",
    int $expires_or_options = 0,
    string $path = "",
    string $domain = "",
    bool $secure = false,
    bool $httponly = false
): bool

Alternative Signatur, verfügbar ab PHP 7.3.0 (benannte Parameter werden nicht unterstützt):

setcookie(string $name, string $value = "", array $options = []): bool

setcookie() definiert ein mit den HTTP-Header-Informationen zu übertragendes Cookie. Wie andere Header auch, müssen Cookies vor jeglicher Ausgabe des Skripts gesendet werden (dies ist eine Einschränkung des Protokolls). Das bedeutet, dass diese Funktion vor jeglicher Ausgabe, einschließlich der Ausgabe von <html>- oder <head>-Tags sowie jeder Art von Whitespace, aufgerufen werden muss.

Sind die Cookies einmal gesetzt, kann beim nächsten Seitenaufruf anhand des $_COOKIE-Arrays auf diese zugegriffen werden. Die Cookie-Werte können auch in $_REQUEST vorhanden sein.

Parameter-Liste

» RFC 6265 liefert die normative Referenz, wie die jeweiligen setcookie()-Parameter interpretiert werden.

name

Der Name des Cookies.

value

Der Wert des Cookies. Dieser Wert wird auf dem Computer des Benutzers gespeichert, weshalb darin keine sensiblen Informationen gespeichert werden sollten. Angenommen der Parameter name ist 'cookiename', so erhält man seinen Wert mittels $_COOKIE['cookiename'].

expires_or_options

Der Zeitpunkt, an dem das Cookie ungültig wird. Dies ist ein Unix-Timestamp, also die Anzahl Sekunden seit Beginn der Unix-Epoche (1. Januar 1970). Eine Möglichkeit, diesen festzulegen, besteht darin, die Anzahl der Sekunden, bevor das Cookie abläuft, zum Ergebnis des Aufrufs von time() zu addieren. Zum Beispiel setzt time()+60*60*24*30 die Verfallszeit des Cookies auf 30 Tage. Eine weitere Möglichkeit ist, die Funktion mktime() zu verwenden. Wenn dieser Parameter auf 0 gesetzt oder weggelassen wird, verfällt das Cookie am Ende der Session (wenn der Browser geschlossen wird).

Hinweis:

Wie bestimmt aufgefallen ist, wird der Parameter expires_or_options als Unix-Timestamp übergeben und nicht im Datumsformat Wdy, DD-Mon-YYYY HH:MM:SS GMT. Die Konvertierung wird von PHP intern durchgeführt.

path

Der Pfad auf dem Server, innerhalb dem das Cookie verfügbar sein wird. Ist er auf '/' gesetzt, wird das Cookie innerhalb der gesamten domain verfügbar. Ist er auf '/foo/' gesetzt, wird das Cookie nur innerhalb des Verzeichnisses /foo/ sowie allen Unterverzeichnissen wie z. B. /foo/bar/ von domain verfügbar. Der Standardwert ist das aktuelle Verzeichnis, in dem das Cookie gesetzt wurde.

domain

Die (Sub)-Domain, der das Cookie zur Verfügung steht. Wird dies auf eine Subdomain (wie 'www.example.com') gesetzt, dann steht dieser Subdomain und allen anderen Subdomains davon (z. B. w2.www.example.com) das Cookie zur Verfügung. Um das Cookie der ganzen Domain zur Verfügung zu stellen (einschließlich aller Subdomains davon), muss der Wert einfach auf den Domainnamen (in diesem Fall 'example.com') gesetzt werden.

Ältere Browser, die noch immer das veraltete » RFC 2109 implementieren, können ein führendes . benötigen, um alle Subdomains abzudecken.

secure

Gibt an, dass das Cookie vom Client nur über eine sichere HTTPS-Verbindung übertragen werden soll. Ist der Wert auf true gesetzt, wird das Cookie nur gesendet, wenn eine sichere Verbindung besteht. Auf der Serverseite muss der Programmierer selbst darauf achten, dass entsprechende Cookies über eine sichere Verbindung gesendet werden (z. B. unter Berücksichtigung von $_SERVER["HTTPS"]).

httponly

Wenn auf true gesetzt, ist das Cookie nur via HTTP-Protokoll zugänglich. Das bedeutet, dass das Cookie nicht mehr für Skriptsprachen wie z. B. JavaScript, auslesbar/veränderbar ist. Es wird vermutet, dass diese Einstellung eine effektive Hilfe sein kann, um Identitätsdiebstahl per XSS-Angriff zu vermindern (obwohl sie nicht von allen Browsern unterstützt wird), diese Behauptung wird jedoch oft angezweifelt. true oder false

options

Ein assoziatives Array, das die Schlüssel expires, path, domain, secure, httponly und samesite enthalten kann. Ist irgendein anderer Schlüssel vorhanden, wird ein Fehler der Stufe E_WARNING generiert. Die Werte haben dieselbe Bedeutung wie für die gleichnamigen Parameter beschrieben. Der Wert des samesite-Elements sollte entweder None, Lax oder Strict sein. Ist eine der erlaubten Optionen nicht angegeben, dann ist ihr Standardwert derselbe wie für den expliziten Parameter. Wird das samesite-Element nicht angegeben, dann wird kein SameSite-Cookie-Attribut gesetzt.

Hinweis:

Um ein Cookie mit Attributen zu setzen, die nicht unter den aufgelisteten Schlüsseln sind, kann die Funktion header() verwendet werden.

Rückgabewerte

Erfolgt eine Ausgabe vor dem Aufruf dieser Funktion, wird setcookie() fehlschlagen und false zurückgeben. Wenn setcookie() erfolgreich durchgeführt wird, wird true zurückgegeben. Dies sagt jedoch nichts darüber aus, ob der Benutzer das Cookie auch akzeptiert hat.

Changelog

Version Beschreibung
8.2.0 Das Datumsformat des gesendeten Cookies ist nun 'D, d M Y H:i:s \G\M\T'; vorher war es 'D, d-M-Y H:i:s T'.
7.3.0 Eine alternative Signatur, die ein options-Array unterstützt, wurde hinzugefügt. Diese Signatur unterstützt auch das Setzen des SameSite-Cookie-Attributs.

Beispiele

Die folgenden Beispiele zeigen einige Möglichkeiten, Cookies zu senden.

Beispiel #1 setcookie()-Beispiele

<?php
$value
= 'irgendetwas von irgendwo';

setcookie("TestCookie", $value);
setcookie("TestCookie", $value, time()+3600); /* verfällt in 1 Stunde */
setcookie("TestCookie", $value, time()+3600, "/~rasmus/", "example.com", 1);
?>

Zu beachten ist, dass der Wertebereich des Cookies automatisch URL-konform kodiert (urlencoded) wird, sobald das Cookie gesendet wird, und es beim Erhalt automatisch dekodiert und einer Variablen zugewiesen wird, die denselben Namen wie das Cookie trägt. Wenn dies nicht gewünscht ist, kann stattdessen setrawcookie() verwendet werden. Um die Inhalte unseres Test-Cookies in einem Skript sichtbar zu machen, kann einfach eines der folgenden Beispiele verwendet werden:

<?php
// ein bestimmtes Cookie ausgeben
echo $_COOKIE["TestCookie"];

// Ein anderer Weg zu Debuggen/Testen ist, alle Cookies anzuzeigen
print_r($_COOKIE);
?>

Beispiel #2 setcookie()-Beispiele zum Löschen

Beim Löschen eines Cookies sollte sichergestellt werden, dass das Verfallsdatum in der Vergangenheit liegt, um den Mechanismus zum Löschen des Cookies im Browser auszulösen. Die folgenden Beispiele zeigen, wie die im vorigen Beispiel gesendeten Cookies wieder gelöscht werden:

<?php
// Setzen des Verfalls-Zeitpunktes auf 1 Stunde in der Vergangenheit
setcookie("TestCookie", "", time() - 3600);
setcookie("TestCookie", "", time() - 3600, "/~rasmus/", "example.com", 1);
?>

Beispiel #3 setcookie() und Arrays

Mit der Array-Schreibweise im Cookienamen kann auch ein Array von Cookies gesetzt werden. Dadurch werden so viele Cookies gesetzt, wie das Array Elemente hat, aber wenn das Cookie vom Skript empfangen wird, werden alle Werte in ein einziges Array mit dem Cookienamen eingelesen:

<?php
// Setzen der Cookies
setcookie("cookie[drei]", "cookiedrei");
setcookie("cookie[zwei]", "cookiezwei");
setcookie("cookie[eins]", "cookieeins");

// Nach dem Neuladen der Seite wieder ausgeben
if (isset($_COOKIE['cookie'])) {
foreach (
$_COOKIE['cookie'] as $name => $value) {
$name = htmlspecialchars($name);
$value = htmlspecialchars($value);
echo
"$name : $value <br />\n";
}
}
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

drei : cookiedrei
zwei : cookiezwei
eins : cookieeins

Hinweis: Die Verwendung von Trennzeichen wie [ und ] als Teil des Cookie-Namens ist nicht konform mit RFC 6265, Abschnitt 4, soll aber laut RFC 6265, Abschnitt 5, von User-Agents unterstützt werden.

Anmerkungen

Hinweis:

Sie können den Ausgabepuffer verwenden, um Ausgaben vor dem Aufruf dieser Funktion duchführen zu können. Dies hat allerdings zur Folge, dass alle Ihre Ausgaben zum Browser auf dem Server zwischengespeichert werden, bis Sie diese senden. Sie können dies in Ihrem Skript mittels der Funktionen ob_start() und ob_end_flush() oder mittels der Konfigurationseinstellung output_buffering in Ihrer php.ini, oder Sie ändern entsprechende Konfigurationseinstellungen am Server.

Häufige Probleme:

  • Cookies werden erst beim nächsten Laden einer Seite sichtbar, für die das Cookie sichtbar sein soll. Um zu testen, ob ein Cookie erfolgreich gesetzt wurde, prüfen Sie noch vor der Ablaufzeit auf der nächsten geladenen Seite, ob das Cookie vorhanden ist. Die Ablaufzeit wird mittels des Parameters expires_or_options gesetzt. Eine gute Möglichkeit, die Existenz von Cookies zu prüfen, ist einfach print_r($_COOKIE); aufzurufen.
  • Cookies müssen mit denselben Parametern gelöscht werden, mit denen sie gesetzt wurden. Ist der value-Parameter ein leerer String und alle anderen Werte entsprechen dem früheren Aufruf von setcookie, wird das Cookie mit dem angegebenen Namen vom Client gelöscht. Dies wird intern ausgeführt, indem der Wert auf 'deleted' gesetzt wird und die Verfallszeit in die Vergangenheit gelegt wird.
  • Da beim Setzen eines Cookies mit dem Wert false versucht wird, das entsprechende Cookie zu löschen, sollten Sie keine boolschen Werte verwenden. Nutzen Sie statt dessen 0 für false und 1 für true.
  • Namen von Cookies können auch als Arraynamen gesetzt werden und stehen dann in Ihren Skripten als Arrays zu Verfügung, während sie auf dem System des Benutzers als separate Cookies abgespeichert werden. Erwägen Sie den Einsatz von explode(), um ein Cookie mit mehreren Namen und Werten zu setzen. Es ist nicht empfehlenswert, zu diesem Zweck serialize() einzusetzen, da hieraus Sicherheitslöcher erwachsen können.

Mehrfache Aufrufe von setcookie() werden in der Reihenfolge ihres Aufrufs ausgeführt.

Siehe auch

add a note add a note

User Contributed Notes 44 notes

up
358
walterquez
11 years ago
Instead of this:
<?php setcookie( "TestCookie", $value, time()+(60*60*24*30) ); ?>

You can this:
<?php setcookie( "TestCookie", $value, strtotime( '+30 days' ) ); ?>
up
204
Bachsau
11 years ago
Want to remove a cookie?

Many people do it the complicated way:
setcookie('name', 'content', time()-3600);

But why do you make it so complicated and risk it not working, when the client's time is wrong? Why fiddle around with time();

Here's the easiest way to unset a cookie:
setcookie('name', 'content', 1);

Thats it.
up
34
Anonymous
3 years ago
Just an example to clarify the use of the array options, especially since Mozilla is going to deprecate / penalise the use of SameSite = none,  which is used by default if not using array options.

<?php
$arr_cookie_options
= array (
               
'expires' => time() + 60*60*24*30,
               
'path' => '/',
               
'domain' => '.example.com', // leading dot for compatibility or use subdomain
               
'secure' => true,     // or false
               
'httponly' => true,    // or false
               
'samesite' => 'None' // None || Lax  || Strict
               
);
setcookie('TestCookie', 'The Cookie Value', $arr_cookie_options);   
?>
up
34
paul nospam AT nospam sitepoint dot com
17 years ago
Note when setting "array cookies" that a separate cookie is set for each element of the array.

On high traffic sites, this can substantially increase the size of subsequent HTTP requests from clients (including requests for static content on the same domain).

More importantly though, the cookie specification says that browsers need only accept 20 cookies per domain.  This limit is increased to 50 by Firefox, and to 30 by Opera, but IE6 and IE7 enforce the limit of 20 cookie per domain.  Any cookies beyond this limit will either knock out an older cookie or be ignored/rejected by the browser.
up
39
Anonymous
17 years ago
something that wasn't made clear to me here and totally confused me for a while was that domain names must contain at least two dots (.), hence 'localhost' is invalid and the browser will refuse to set the cookie! instead for localhost you should use false.

to make your code work on both localhost and a proper domain, you can do this:

<?php

$domain
= ($_SERVER['HTTP_HOST'] != 'localhost') ? $_SERVER['HTTP_HOST'] : false;
setcookie('cookiename', 'data', time()+60*60*24*365, '/', $domain, false);

?>
up
16
nacho at casinelli dot com
7 years ago
It's worth a mention: you should avoid dots on cookie names.

<?php
// this will actually set 'ace_fontSize' name:
setcookie( 'ace.fontSize', 18 );
?>
up
9
user at example.com
4 years ago
As of PHP 7.3.0 the setcookie() method supports the SameSite attribute in its options and will accept None as a valid value.

For earlier versions of PHP,  you can set the header() directly:

header('Set-Cookie: cross-site-cookie=bar; SameSite=None; Secure');
up
17
gabe at fijiwebdesign dot com
17 years ago
If you want to delete all cookies on your domain, you may want to use the value of:

<?php $_SERVER['HTTP_COOKIE'] ?>

rather than:

<?php $_COOKIE ?>

to dertermine the cookie names.
If cookie names are in Array notation, eg: user[username]
Then PHP will automatically create a corresponding array in $_COOKIE. Instead use $_SERVER['HTTP_COOKIE'] as it mirrors the actual HTTP Request header.

<?php

// unset cookies
if (isset($_SERVER['HTTP_COOKIE'])) {
   
$cookies = explode(';', $_SERVER['HTTP_COOKIE']);
    foreach(
$cookies as $cookie) {
       
$parts = explode('=', $cookie);
       
$name = trim($parts[0]);
       
setcookie($name, '', time()-1000);
       
setcookie($name, '', time()-1000, '/');
    }
}

?>
up
1
Anonymous
3 years ago
Chrome versions prior to version 67 reject samesite=none cookies. And starting in Chrome version 84 samesite=none cookies without the secure attribute are also rejected. But that doesn't mean you can't set cookies on an unencrypted connection. The simple way around it is to use browser sniffing to detect samesite=none compatible browsers:

$cookie_string = 'set-cookie: name=value';

if (!preg_match('/Chrom[^ \/]+\/([0-9]+)[\.0-9]* /', $_SERVER['HTTP_USER_AGENT'], $matches) || $matches[1]>66 && $matches[1]<84) {// match samesite=none compatible browsers
    $cookie_string.= '; samesite=none';
}

header($cookie_string, false);// set cookie
up
6
synnus at gmail dot com
3 years ago
The " PHPSESSID " cookie will soon be rejected because its " sameSite " attribute is set to " none " or an invalid value, and without " secure " attribute. To learn more about the "sameSite" attribute, visit https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite.

<?php
ini_set
("session.cookie_secure", 1);
session_start();

my PHP code ....

?>
up
13
bluewaterbob
16 years ago
if you are having problems seeing cookies sometimes or deleting cookies sometimes, despite following the advice below, make sure you are setting the cookie with the domain argument. Set it with the dot before the domain as the examples show: ".example.com".  I wasn't specifying the domain, and finally realized I was setting the cookie when the browser url had the http://www.example.com and later trying to delete it when the url didn't have the www. ie. http://example.com. This also caused the page to be unable to find the cookie when the www. wasn't in the domain.  (When you add the domain argument to the setcookie code that creates the cookie, make sure you also add it to the code that deletes the cookie.)
up
11
MrXCol
12 years ago
If you're having problem with IE not accepting session cookies this could help:

It seems the IE (6, 7, 8 and 9) do not accept the part 'Expire=0' when setting a session cookie. To fix it just don't put any expire at all. The default behavior when the 'Expire' is not set is to set the cookie as a session one.

(Firefox doesn't complains, btw.)
up
3
dmitry dot koterov at gmail dot com
8 years ago
Note that at least in PHP 5.5 setcookie() removes previously set cookies with the same name (even if you've set them via header()), so previously fired Set-Cookie headers with e.g. PHPSESSID name are not flushed to the browser. Even headers_list() doesn't see them after session_start():

header("Set-Cookie: PHPSESSID=abc; path=/; domain=.sub.domain.com");
header("Set-Cookie: PHPSESSID=abc; path=/; domain=.domain.com");
print_r(headers_list()); // here you see two Set-Cookie headers with domains for PHPSESSID
session_id('abc');
session_start();
print_r(headers_list()); // here you don't; you see only one Set-Cookie produced by session_start()
up
4
lferro9000 at gmail dot com
7 years ago
Of notice, the cookie when set with a zero expire or ommited WILL not expire when the browser closes.

What happens is that the browser, when closes the window, if it is a well behaved browser, will delete the cookie from the cookie store.

However, the cookie will survive in the server until the garbage collector removes the session, which will happen only when it kicks in and checks the specified session is out of bounds of the setting stated in:

http://php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime

Please check also:

http://php.net/manual/en/session.security.ini.php

And in case of doubt, PHP runs on the webserver and has no way whatsoever to interact with a browser apart from receiving requests and answering with responses, so assuming that a cookie will be removed from a browser is just an "hint" for the browser. There is no warranty that such will happen as instructed.

That is one of the reasons why the cookie values sent to browsers by some platforms are encrypted and timestamped, to ensure that they are actual and not tampered.
up
7
ellert at vankoperen dot nl
9 years ago
Caveat: if you use URL RewriteRules to get stuff like this: domain.com/bla/stuf/etc into parameters, you might run into a hickup when setting cookies.
At least in my setup a change in one of the parameters resulted in the cookie not being 'there' anymore.
The fix is simple: specify the domain. '/' will usualy do fine.
up
8
gareth at gw126 dot com
17 years ago
You can use cookies to prevent a browser refresh repeating some action from a form post... (providing the client is cookie enabled!)

<?php
//Flag up repeat actions (like credit card transaction, etc)
if(count($_POST)>0) {
   
$lastpost= isset($_COOKIE['lastpost']) ? $_COOKIE['lastpost'] : '';
    if(
$lastpost!=md5(serialize($_POST))) {
       
setcookie('lastpost', md5(serialize($_POST)));
       
$_POST['_REPEATED']=0;
    } else {
       
$_POST['_REPEATED']=1;
    }
}

//At this point, if $_POST['_REPEATED']==1, then  the user
//has hit the refresh button; so don't do any actions that you don't
//want to repeat!
?>

Hope that helps :)

Gareth
up
9
Eric
14 years ago
The server my php code is running on has sessions disabled so I am forced to store a fair bit of arbitrary data in cookies.  Using array names was impractical and problematic, so I implemented a splitting routine.  I do not serialize any class instances, just arrays and simple objects.

In a nutshell, when setting a cookie value, I serialize it, gzcompress it, base64 encode it, break it into pieces and store it as a set of cookies.  To fetch the cookie value I get the named piece then iterate through piece names rebuilding the base64 data, then reverse the rest of the process.  The only other trick is deleting the pieces correctly.

Sessions are better, but if they are not available this is a viable alternative.  I chose gz over bz for compression because it looked faster with only slightly worse ratios.

Here is a simplified version of my implementation.  This is a good starting point but is not suitable for most uses.  For example, the domain and path are hard coded and no return values are checked for validity.

<?php
define
( 'COOKIE_PORTIONS' , '_piece_' );

function
clearpieces( $inKey , $inFirst ) {
   
$expire = time()-3600;
   
    for (
$index = $inFirst ; array_key_exists( $inKey.COOKIE_PORTIONS.$index , $_COOKIE ) ; $index += 1 ) {
       
setcookie( $inKey.COOKIE_PORTIONS.$index , '' , $expire , '/' , '' , 0 );
        unset(
$_COOKIE[$inKey.COOKIE_PORTIONS.$index] );
    }
}

function
clearcookie( $inKey ) {
   
clearpieces( $inKey , 1 );
   
setcookie( $inKey , '' , time()-3600 , '/' , '' , 0 );
    unset(
$_COOKIE[$inKey] );
}

function
storecookie( $inKey , $inValue , $inExpire ) {
   
$decode = serialize( $inValue );
   
$decode = gzcompress( $decode );
   
$decode = base64_encode( $decode );
   
   
$split = str_split( $decode , 4000 );//4k pieces
   
$count = count( $split );
   
    for (
$index = 0 ; $index < $count ; $index += 1 ) {
       
$result = setcookie( ( $index > 0 ) ? $inKey.COOKIE_PORTIONS.$index : $inKey , $split[$index] , $inExpire , '/' , '' , 0 );
    }
   
   
clearpieces( $inKey , $count );
}

function
fetchcookie( $inKey ) {
   
$decode = $_COOKIE[$inKey];
   
    for (
$index = 1 ; array_key_exists( $inKey.COOKIE_PORTIONS.$index , $_COOKIE ) ; $index += 1 ) {
       
$decode .= $_COOKIE[$inKey.COOKIE_PORTIONS.$index];
    }
   
   
$decode = base64_decode( $decode );
   
$decode = gzuncompress( $decode );
   
    return
unserialize( $decode );
}
?>
up
6
jay at w3prodigy dot com
13 years ago
You can also delete cookies by supplying setcookie an empty value.

setcookie("w3p_cookie", "");
up
7
jdknock (at) gMaIl (dot) com
13 years ago
IE7 can have trouble with settings cookies that are embedded in an iframe. The problem lies with a W3C standard called Platform for Privacy Preferences or P3P for short.

To overcome, include the header:

header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');

before setting the cookie.
up
7
ahmetantmen at msn dot com
17 years ago
You can be sure about the cookie files contents weren't changed.

<?php

$Seperator
= '--';
$uniqueID = 'Ju?hG&F0yh9?=/6*GVfd-d8u6f86hp';
$Data = 'Ahmet '.md5('123456789');

setcookie('VerifyUser', $Data.$Seperator.md5($Data.$uniqueID));

if (
$_COOKIE) {
  
$Cut = explode($Seperator, $_COOKIE['VerifyUser']);
   if (
md5($Cut[0].$uniqueID) === $Cut[1]) {
      
$_COOKIE['VerifyUser'] = $Cut[0];
   } else {
       die(
'Cookie data is invalid!!!');
   }
}

echo
$_COOKIE['VerifyUser'];

?>

Create a unique id for your site and create a hash with md5($Data.$uniqueID). Attacker can understant that it must be re-hash after change cookie content.
But doesn't. Because cannot guess your unique id. Seperate your hash and data with seperator and send that cookie. Control that hash of returned value and your unique id's is same returned hash. Otherwise you have to stop attack. Sorry for my poor english!
up
7
Carl V
18 years ago
If you want to delete all the cookies set by your domain, you may run the following:

<?php
$cookiesSet
= array_keys($_COOKIE);
for (
$x=0;$x<count($cookiesSet);$x++) setcookie($cookiesSet[$x],"",time()-1);
?>

Very useful when doing logout scripts and the cookie name may have changed (long story).
up
3
isooik at gmail-antispam dot com
16 years ago
Here's a more advanced version of the php setcookie() alternative function:

<?php

   
/**
     * A better alternative (RFC 2109 compatible) to the php setcookie() function
     *
     * @param string Name of the cookie
     * @param string Value of the cookie
     * @param int Lifetime of the cookie
     * @param string Path where the cookie can be used
     * @param string Domain which can read the cookie
     * @param bool Secure mode?
     * @param bool Only allow HTTP usage?
     * @return bool True or false whether the method has successfully run
     */
   
function createCookie($name, $value='', $maxage=0, $path='', $domain='', $secure=false, $HTTPOnly=false)
    {
       
$ob = ini_get('output_buffering');

       
// Abort the method if headers have already been sent, except when output buffering has been enabled
       
if ( headers_sent() && (bool) $ob === false || strtolower($ob) == 'off' )
            return
false;

        if ( !empty(
$domain) )
        {
           
// Fix the domain to accept domains with and without 'www.'.
           
if ( strtolower( substr($domain, 0, 4) ) == 'www.' ) $domain = substr($domain, 4);
           
// Add the dot prefix to ensure compatibility with subdomains
           
if ( substr($domain, 0, 1) != '.' ) $domain = '.'.$domain;

           
// Remove port information.
           
$port = strpos($domain, ':');

            if (
$port !== false ) $domain = substr($domain, 0, $port);
        }

       
// Prevent "headers already sent" error with utf8 support (BOM)
        //if ( utf8_support ) header('Content-Type: text/html; charset=utf-8');

       
header('Set-Cookie: '.rawurlencode($name).'='.rawurlencode($value)
                                    .(empty(
$domain) ? '' : '; Domain='.$domain)
                                    .(empty(
$maxage) ? '' : '; Max-Age='.$maxage)
                                    .(empty(
$path) ? '' : '; Path='.$path)
                                    .(!
$secure ? '' : '; Secure')
                                    .(!
$HTTPOnly ? '' : '; HttpOnly'), false);
        return
true;
    }

?>

Regards,
Isaak
up
3
hansel at gretel dot com
17 years ago
The following code snippet combines abdullah's and Charles Martin's examples into a powerful combination function (and fixes at least one bug in the process):

<?php
 
function set_cookie_fix_domain($Name, $Value = '', $Expires = 0, $Path = '', $Domain = '', $Secure = false, $HTTPOnly = false)
  {
    if (!empty(
$Domain))
    {
     
// Fix the domain to accept domains with and without 'www.'.
     
if (strtolower(substr($Domain, 0, 4)) == 'www.'$Domain = substr($Domain, 4);
     
$Domain = '.' . $Domain;

     
// Remove port information.
     
$Port = strpos($Domain, ':');
      if (
$Port !== false$Domain = substr($Domain, 0, $Port);
    }

   
header('Set-Cookie: ' . rawurlencode($Name) . '=' . rawurlencode($Value)
                          . (empty(
$Expires) ? '' : '; expires=' . gmdate('D, d-M-Y H:i:s', $Expires) . ' GMT')
                          . (empty(
$Path) ? '' : '; path=' . $Path)
                          . (empty(
$Domain) ? '' : '; domain=' . $Domain)
                          . (!
$Secure ? '' : '; secure')
                          . (!
$HTTPOnly ? '' : '; HttpOnly'), false);
  }
?>

Basically, if the domain parameter is supplied, it is converted to support a broader range of domains.  This behavior may or may not be desireable (e.g. could be a security problem depending on the server) but it makes cookie handling oh-so-much-nicer (IMO).
up
5
laffen
14 years ago
Note that the $_COOKIE variable not will hold multiple cookies with the same name. It is legitimate to set two cookies with the same name to the same host where the sub domain is different.
<?php
setcookie
("testcookie", "value1hostonly", time(), "/", ".example.com", 0, true);
setcookie("testcookie", "value2subdom", time(), "/", "subdom.example.com", 0, true);
?>
The next request from the browser will have both cookies in the $_SERVER['HTTP_COOKIE'] variable, but only one of them will be found in the $_COOKIE variable. Requests to subdom.example.com will have both cookies, while browser request to example.com or www.example.com only sends the cookie with the "value1hostonly" value.

<?php
$kaker
= explode(";", $_SERVER['HTTP_COOKIE']);
foreach(
$kaker as $val){
   
$k = explode("=", $val);
    echo
trim($k[0]) . " => " . $k[1];
}

// output
testcookie => value1hostonly
testcookie
=> value2subdom

?>
up
8
jonathan dot bergeron at rve dot ulaval dot ca
16 years ago
About the delete part, I found that Firefox only remove the cookie when you submit the same values for all parameters, except the date, which sould be in the past. Submiting blank values didn't work for me.

Example :
- set -

<?php setcookie( "name", "value", "future_timestamp", "path", "domain" ); ?>

- delete -
<?php setcookie( "name", "value", "past_timestamp", "path", "domain" ); ?>

Jonathan
up
5
cwillard at fastmail dot fm
16 years ago
If you're looking to set multiple values in your cookie (rather than setting multiple cookies) you might find these useful.

<?php
function build_cookie($var_array) {
  if (
is_array($var_array)) {
    foreach (
$var_array as $index => $data) {
     
$out.= ($data!="") ? $index."=".$data."|" : "";
    }
  }
  return
rtrim($out,"|");
}

function
break_cookie ($cookie_string) {
 
$array=explode("|",$cookie_string);
  foreach (
$array as $i=>$stuff) {
   
$stuff=explode("=",$stuff);
   
$array[$stuff[0]]=$stuff[1];
    unset(
$array[$i]);
  }
  return
$array;
}
?>
Hopefully someone finds these useful.
up
3
Anonymous
13 years ago
A period in a cookie name (like user.name) seems to show up in the $_COOKIE array as an underscore (so user_name). This means that for example $_COOKIE["user_name"] must be used to read a cookie that has been set with setcookie("user.name" ...), which is already rather confusing.

Furthermore the variable $_COOKIE["user_name"] will retain the value set by setcookie("user.name" ...) and no amount of calling setcookie("user_name" ...) will alter this value. This is rather trivially fixed by clearing the "user.name" cookie, but it can take a while to realize this since there's only "user_name" in $_COOKIE.

Hope this saves someone some time.
up
4
mkmohsinali at gmail dot com
12 years ago
#cookies.php
/*This code will demonstrate use of cookies with PHP
It is very easy to understand and is better for beginner to
understand and get idea about power of cookies when used
with PHP.Here we give user a form to choose colors he/she
likes for website and when he/she visits site again within one
hour his/her settings are saved and read from cookie
and he/she doesn't have to set the page color and page
text color again.You can change time from 3600
seconds to whatever you deem appropriate in your case.
if you don't understand anything please email me*/

<?php
#checking if form has been submitted
if (isset($_POST['submitted'])){
#if yes (form is submitted) assign values from POST array to variables
$newbgColor=$_POST['bgColor'];
$newtxtColor=$_POST['txtColor'];
#set cookies
setcookie("bgColor",$newbgColor,time()+3600);
setcookie("txtColor",$newtxtColor,time()+3600);

}
#in case user has come for first time and cookies are not set then
if ((!isset($_COOKIE['bgColor']) ) && (!isset($_COOKIE['txtColor']))){
$bgColor = "Black";
$txtColor="White";
}
#if cookies are set then use them
else{
$bgColor = $_COOKIE['bgColor'];
$txtColor = $_COOKIE['txtColor'];
}
?>
<!-- HTML Page-->
<html>
<body bgcolor="<?php echo $bgColor ?>" text="<?php echo $txtColor ?>">
<form action= "<?php echo $_SERVER['PHP_SELF']; ?>" method ="POST">
<p>Body Color:</p>
<select name=bgColor>
<option value ="Red">Red</option>
<option value ="Green" selected>Green</option>
<option value ="Blue">Blue</option>
<option value ="Yellow">Yellow</option>
<option value ="Black">Black</option>
<option value ="Brown">Brown</option>
<option value ="White">White</option>
</select>
<p>Text Color:</p>
<select name=txtColor>
<tion value ="Red">Red</option>
<option value ="Green" selected>Green</option>
<option value ="Blue">Blue</option>
<option value ="Yellow">Yellow</option>
<option value ="Black">Black</option>
<option value ="Brown">Brown</option>
<option value ="White">White</option>
</select>
<input type ="hidden" name="submitted" value="true"></br>
<input type="submit" value="remind">
</form>
</body>
</html>
up
3
bocian941 at pawno dot pl
12 years ago
My 2 functions to use "live cookies":

<?php
   
function SetCookieLive($name, $value='', $expire = 0, $path = '', $domain='', $secure=false, $httponly=false)
    {
       
$_COOKIE[$name] = $value;
        return
setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
    }

    function
RemoveCookieLive($name)
    {
        unset(
$_COOKIE[$name]);
        return
setcookie($name, NULL, -1);
    }
?>
up
2
stovenator at gmail dot com
17 years ago
If you are having issues with IE7 and setcookie(), be sure to verify that the cookie is set via http for http sites, and https for https site.

Also, if the time is incorrect on your server, IE7 will also disallow those cookies from being set.
up
1
chris at styl dot ee
12 years ago
I was searching for a simple example of creating a cookie, storing a random number and updating it on refresh. I couldn't find one so I had to figure it out on my own....

- - - -
One thing to *NOTE* is technically you can't update a cookie, you can only overwrite it with a new one with the same name.

- - - -

This creates a random number, stores it in a cookie, then references it on refresh, checks for duplicates and does necessary correction, then stores it again, rinse and repeat...

<?php
ob_start
();
$MaxCount = 4;// set the max of the counter, in my tests "4" = (0,1,2,3) I adjusted below (+1) to get a "real" 4 (0,1,2,3,4) this is in reality 5 keys to humans, you can adjust script to eliminate "0", but my script makes use of the "0"

$random =(rand()%($MaxCount+1));//give me a random number limited by the max, adding "1" because computers start counting at "0"

if(!isset($_COOKIE['random'])){// check if random number cookie is not set
    //echo"not set";
   
setcookie('random', $random);//set the cookie for the first time
   
}else{
   
$lastRandom= $_COOKIE['random']; //hold the last number if it was set before
   
if($lastRandom == $random){//some logic to avoid repeats
    
if($random < $MaxCount){//if below max, add 1
       
$random++;
       
//echo "under the max, adding 1, ";   
   
}elseif($random >= ($MaxCount-1)){// if for some reason the random number is more than max or equal to it -1, and an additional -1 for max count in initial var (so in reality this -1 from intial max var, and -1 from $random which should be the same number)
           
$random--;
           
//echo "hit the max, subtracting 1, ";
       
}else{
       
$random++;
       
//echo "no case match, adding 1, ";   
       
}
   
//echo "(".$lastRandom.", ".$random. "), they matched initally - was it fixed?";
   
}else{
   
//echo "(".$lastRandom.", ".$random. "), they DO NOT match";
   
setcookie('random', $random);   
    }
   
//echo"is set: {$_COOKIE['random']}";
}

ob_end_flush();

?>
up
1
mike
16 years ago
Be careful of using the same cookie name in subdirectories. Setting a simple cookie

<?php setcookie("region", $_GET['set_region']); ?>

both in the root / and for instance in this case /admin/ will create 2 cookies with different paths. In reading the cookies back only the first one is read regardless of path.
up
0
Anonymous
3 years ago
To add the "samesite" attribute, you can concatenate it to the path option until it gets implemented/documented properly
Eg:
<?php
    setcookie
('cookie_name', 'cookie_value', 0, '/; SameSite=strict');
?>
up
0
niall at maranelda dot org
4 years ago
Be warned! PHP will mangle the names of incoming cookies far more than others have detailed below!

Theoretically, the following non-alphanumeric characters are allowed in a cookie name:

!#$%&'()*+-./:<>?@[]^_`{|}~

However, if you do this:

<?php
    setcookie
('!#$%&\'()*+-./:<>?@[]^_`{|}~', 123);
   
setcookie('!#$%&\'()*+-./:<>?@[^_`{|}~', 466);
   
setcookie('!#$%&\'()*+-./:<>?@]^_`{|}~', 789);
   
setcookie('!#$%&\'()*+-./:<>?@^_`{|}~', 'abc');
?>

then this:

<?php
    print_r
($_COOKIE);
?>

you get this back:

<?php
Array
(
    [!
#$%&'()*_-_/:<>?@] => Array
       
(
            [
0] => 123
       
)

    [!
#$%&'()*_-_/:<>?@_^_`{|}~] => 456
   
[!#$%&'()*_-_/:<>?@]^_`{|}~] => 789
   
[!#$%&'()*_-_/:<>?@^_`{|}~] => abc
)
?>

The rules would appear to be as follows:

- Convert all periods to underscores (as detailed below).
- Convert all plus signs to underscores.
- Convert all unmatched open square brackets to underscores.
- Square bracket pairs mean the value is an array; ignore everything after the closing square bracket.

Note that these rules are only applied by PHP when generating the $_COOKIE array; the cookie name part in the headers sent by your browser and as received by PHP are exactly as you specified above;

<?php
   
echo $_SERVER['HTTP_COOKIE'];
?>

gives

<?php
   
!#$%&'()*+-./:<>?@[]^_`{|}~=123; !#$%&'()*+-./:<>?@[^_`{|}~=456; !#$%&'()*+-./:<>?@]^_`{|}~=789; !#$%&'()*+-./:<>?@^_`{|}~=abc
?>

It would be nice if the official notes mentioned this conversion.
up
1
Anonymous
5 years ago
I haven't seen this mentioned here and had a lot of issues (and created a lot of stupid hacks) before I figured this out.

If you have a couple of environments for example, and are trying to set cookies on two domains:

example.com (main site)
dev.example.com (dev site)

In this case your (same named) cookies will interfere with each other if you're trying to set cookies with the domain parameter. 

Simply use an empty string for the domain parameter and the cookies will refer to each host separately.

If you use the subdomain www. on the main site this won't be an issue, but without a subdomain you'll have issues with reading each others' cookies.
up
0
byz
7 years ago
exmaple with test.com;

setcookie('empty_domain','value',time()+3600,'') 
equal       test.com

setcookie('test_com_domain','value',time()+3600,'','test.com')  
equal       .test.com

setcookie('dot_test_com_domain','value',time()+3600,'','.test.com') 
equal       .test.com

ps:   .test.com   has its self    and child domain
up
0
Anonymous
16 years ago
if you only want to do something once per unique visitor, you can test if a cookie is set, and if not, set the cookie and perform the action. This being the poorman's version, it has a problem, where if a user is blocking cookies they will appear as a first time visitor each time. What you can do to avoid this is to set a test cookie first and check that it exists. If it exists, then check to see if your second cookie has been set. If the first one is set, but the second isn't, then you know this is a first time visitor.
up
0
J?rg Aldinger
20 years ago
When using your cookies on a webserver that is not on the standard port 80, you should NOT include the :[port] in the "Cookie domain" parameter, since this would not be recognized correctly.
I had the issue working on a project that runs on multiple servers (development, production, etc.). One of the servers is running on a different port (together with other websites that run on the same server but on different ports).
up
-1
adruff at gmail dot com
17 years ago
If you intend to use persistent cookies (vice session cookies that are deleted when the browser is closed) be aware:
1) Firefox appears to require that you include all paramaters, or it will ignore the expiration and treat the cookie as a session cookie
2) My version of firefox (1.5.0.6) defaults to 'keep cookies until i close firefox' , which essentially makes every cookie a session cookie. This of course sucks for devs, but i suppose is supposed to be a security feature for the end user. If the user wants to configure firefox to respect the expiration date and retain cookies beyond the session, the user must change it to 'keep cookies until they expire'.
up
-2
RC
13 years ago
For those of your banging your head as to why a cookie is not present when Internet Explorer 6 prints, the explanation is quite interesting. After a bit of investigation, a cookie with an expiration time other than 0 fails to be passed from IE6 to the server when printing. A cookie with an expiration time of 0 is sent.

Therefore:

setcookie("TestCookie", $value, time()+3600); //will not be sent from Print / Print Preview in IE6

setcookie("TestCookie", $value, 0); //will be sent from Print / Print Preview in IE6

I'll let everyone figure out who's bright idea it was to not send normal expiring cookies when printing in IE6...
up
-1
dont at mail dot me
7 years ago
> "When deleting a cookie you should assure that the expiration date is in the past, to trigger the removal mechanism in your browser"

This part of the documentation is no longer accurate. On my version of PHP (5.6.28) setting a null, empty string or boolean false value causes the server to ignore your expire date parameter and always sends value "deleted" and expire date 1970-01-01 00:00:01.
up
-3
apex at xepa dot nl
20 years ago
Note on setting cookies allowing access to sites:

If you are not using something "personal" from the computer that you are sending the cookie too watch out.  Via javascript it is possible to steal cookies from other users.  Thus allowing the stealer to login to your site as another user that might not have access otherwise.  Try to add something like the user's ip in the cookie and allowing access from that ip only with the stored cookie data.

[Editor's note: ... or simply use sessions. You can't be sure that the visitor will use the same IP the next visit. Not even on the next request (thanks to proxy servers)]
up
-2
stuff at joneva dot de
6 years ago
How to store a cookie in php with JSON and read it in JavaScript correctly without using setcookieraw

$defaultActions = array(
                '1' => '0',
                '2' => '0',
                '3' => '0',
                '4' => '0',
                '5' => '0',
                '6' => '0',
                '7' => '0',
                '8' => '0',
                '9' => '0',
                '10' => '0'
            );
$json_str = json_encode($defaultActions);

//delete all cookies
if (isset($_SERVER['HTTP_COOKIE'])) {
    $cookies = explode(';', $_SERVER['HTTP_COOKIE']);
    foreach($cookies as $cookie) {
        $parts = explode('=', $cookie);
        $name = trim($parts[0]);
        setcookie($name, '', time()-1000);
        setcookie($name, '', time()-1000, '/');
    }
}
//setrawcookie("test", $json_str, false,"/",false);

setcookie("test", $json_str, false,"/",false);

?>

<script type="text/javascript">
   
    function getCookie(name) {
        var value = "; " + document.cookie;
        var parts = value.split("; " + name + "=");
        if (parts.length == 2)
            return parts.pop().split(";").shift();
    }
   
    console.log(decodeURIComponent(getCookie('test')));
   
</script>
up
-10
fapchat at gmail dot com
4 years ago
Instead of this:
<?php setcookie( "TestCookie", $value, strtotime( '+30 days' ) ); ?>

You can this:
<?php setcookie( "TestCookie"); ?>
To Top