Descrierea

setcookie() defines a cookie to be sent along with the
rest of the HTTP headers. Like other headers, cookies must be sent
before any output from your script (this is a
protocol restriction). This requires that you place calls to this function
prior to any output, including <html> and
<head> tags as well as any whitespace.

Once the cookies have been set, they can be accessed on the next page load
with the $_COOKIE array.
Cookie
values may also exist in $_REQUEST.

Parametri

» RFC 6265 provides the normative
reference on how each setcookie() parameter is
interpreted.

name

The name of the cookie.

value

The value of the cookie. This value is stored on the clients computer;
do not store sensitive information. Assuming the
name is 'cookiename', this
value is retrieved through $_COOKIE['cookiename']

expire

The time the cookie expires. This is a Unix timestamp so is
in number of seconds since the epoch. In other words, you'll
most likely set this with the time() function
plus the number of seconds before you want it to expire. Or
you might use mktime().
time()+60*60*24*30 will set the cookie to
expire in 30 days. If set to 0, or omitted, the cookie will expire at
the end of the session (when the browser closes).

Notă:

You may notice the expire parameter takes on a
Unix timestamp, as opposed to the date format Wdy, DD-Mon-YYYY
HH:MM:SS GMT, this is because PHP does this conversion
internally.

path

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.

domain

The (sub)domain that the cookie is available to. Setting this to a
subdomain (such as 'www.example.com') will make the
cookie available to that subdomain and all other sub-domains of it (i.e.
w2.www.example.com). To make the cookie available to the whole domain
(including all subdomains of it), simply set the value to the domain
name ('example.com', in this case).

Older browsers still implementing the deprecated
» RFC 2109 may require a leading
. to match all subdomains.

secure

Indicates that the cookie should only be transmitted over a
secure HTTPS connection from the client. When set to TRUE, the
cookie will only be set if a secure connection exists.
On the server-side, it's on the programmer to send this
kind of cookie only on secure connection (e.g. with respect to
$_SERVER["HTTPS"]).

httponly

When TRUE the cookie will be made accessible only through the HTTP
protocol. This means that the cookie won't be accessible by
scripting languages, such as JavaScript. It has been suggested that
this setting can effectively help to reduce identity theft through
XSS attacks (although it is not supported by all browsers), but that
claim is often disputed. Added in PHP 5.2.0.
TRUE or FALSE

Valorile întoarse

If output exists prior to calling this function,
setcookie() will fail and return FALSE. If
setcookie() successfully runs, it will return TRUE.
This does not indicate whether the user accepted the cookie.

Note that the value portion of the cookie will automatically be
urlencoded when you send the cookie, and when it is received, it
is automatically decoded and assigned to a variable by the same
name as the cookie name. If you don't want this, you can use
setrawcookie() instead if you are using PHP 5. To see
the contents of our test cookie in a script, simply use one of the
following examples:

<?php// Print an individual cookieecho $_COOKIE["TestCookie"];

// Another way to debug/test is to view all cookiesprint_r($_COOKIE);?>

Example #2 setcookie() delete example

When deleting a cookie you should assure that the expiration date
is in the past, to trigger the removal mechanism in your browser.
Examples follow how to delete cookies sent in previous example:

You may also set array cookies by using array notation in the
cookie name. This has the effect of setting as many cookies as
you have array elements, but when the cookie is received by your
script, the values are all placed in an array with the cookie's
name:

Istoricul schimbărilor

Versiune

Descriere

5.5.0

A Max-Age attribute is now included in the Set-Cookie header sent to
the client.

5.2.0

The httponly parameter was added.

Note

Notă:

You can use output buffering to send output prior to the
call of this function, with the overhead of all of your output to the
browser being buffered in the server until you send it. You can do this
by calling ob_start() and
ob_end_flush() in your script, or setting the
output_buffering configuration directive on in your
php.ini or server configuration files.

Notă:

If the PHP directive register_globals
is set to on then cookie values will also be made into
variables. In our examples below, $TestCookie will
exist. It's recommended to use $_COOKIE.

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

Cookies must be deleted with the same parameters as they were set with.
If the value argument is an empty string, or FALSE, and all other arguments
match a previous call to setcookie, then the cookie with the specified
name will be deleted from the remote client.
This is internally achieved by setting value to 'deleted' and expiration
time to one year in past.

Because setting a cookie with a value of FALSE will try to delete the cookie,
you should not use boolean values. Instead, use 0 for FALSE
and 1 for TRUE.

Cookies names can be set as array names and will be available to your
PHP scripts as arrays but separate cookies are stored on the user's
system. Consider explode() to set one cookie with
multiple names and values. It is not recommended to use
serialize() for this purpose, because it can result
in security holes.

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.

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:

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.

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.

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

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:

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.

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.

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.

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)]

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. <?phpsetcookie("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.

#cookies.php/*This code will demonstrate use of cookies with PHPIt is very easy to understand and is better for beginner tounderstand and get idea about power of cookies when usedwith PHP.Here we give user a form to choose colors he/shelikes for website and when he/she visits site again within onehour his/her settings are saved and read from cookie and he/she doesn't have to set the page color and pagetext color again.You can change time from 3600seconds to whatever you deem appropriate in your case.if you don't understand anything please email me*/

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

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.

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.

A few comments have suggested using serialize() to set object or array data into a cookie. There are a couple of reasons to be carefull with that technique:

Security: If the cookie is human readable, then it is also fairly easy for end users to play around with it. Wrapping your cookie setting and getting in an encryption routine will prevent tampering, and make sure that your cookies don't make any sense to any client-side exploits or other sites they get sent to thanks to browser bugs.

Bulk: If you serialize even a fairly simple class, then you get a lot of data. Large cookies will make browser requests fat and slow, and some browsers have a limit on cookie size, so think about what data you really need to persist, and create __sleep() and __wakeup() methods to package the data into the shortest possible form. You can get better and faster results when you write your own __sleep() and __wakup() to implode() or pack() your data, than by using zlib compress() on the serialized object.

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

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!

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

> "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.

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 PHPSESSIDsession_id('abc');session_start();print_r(headers_list()); // here you don't; you see only one Set-Cookie produced by session_start()

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

<?phpob_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 beforeif($lastRandom == $random){//some logic to avoid repeatsif($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']}";}

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.

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

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 cookie2) 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'.

I have been tearing my hair out wondering why a cookie would not delete. Despite countless discussions of reasons this can happen all over the internet, none of them addresses my case. Here is what was happening:

My cookies have been formed kindof as an array, and the name of the cookie to be deleted is being passed in a variable, so I was using this to attempt to delete the cookie (stripped to the minimum for simplicity of the example):

<?php setcookie("$cookiename[id]");?>

But it simply would not work. Ultimately what DID work was this:

<?php setcookie($cookiename."[id]");?>

So I had to concatenate the variable to the "element id" and then the cookies deleted without any issue.

Hei, so here is what problem I had, maybe it will help someone in the future:I couldn't delete a cookie, not even set it a different value. I think that is because it had a name following the rule FirstSecondThird. So it had uppercase letters. After I modified the name everithing worked.

Another note:Just for safety you should put what you want to put in the cookie in a var first.

I've been pulling my hair for a couple of minutes (read: hours) and finally figured out why setcookie in my case, returned the "headers already sent"-error:

The file in question was orignally saved as ANSI in Notepad and worked flawlessly, but when saved with UTF-8-encoding, it didn't work. So after trying phpDesigner 7, I was able to both save the file in UTF-8 AND remove the BOM (byte-order-mark which is output BEFORE the cookie is set and thereby fails everything).

Please note that setting the expiry to some timestamp in the past is a common way to get rid of a cookie. However, depending on the value you might set to "invalidate" a cookie immediately, this may pose a threat to the privacy of your user's data, especially when it comes to session cookies.

If you write "0" and "expire-in-the-past" into a session cookie, it remains on the client-side until the clean-up mechanism of the browser hits. (That might be anything from no-time to a very long time. I'm not even thinking of app-based mobile browsers that won't close properly or do their best to ignore standards and RFCs and stuff...)

So, if you have sufficiently messed up your ways of picking up existing session IDs and write-closing their data to your server, the session's data might move from file "sess_(random)" to "sess_0", because that is exactly the identifier that is referred in the cookie.

From now on (at least until your server decides to clean up) there is data laying open wide to anyone requesting the session "0". Which may happen by accident (i.e. another user gains an own "0"-cookie) or malice (i.e. forgery).

Long story short, ALWAYS use an empty string instead of a "0" value for invalidating a session cookie.

P3P is a good idea. But.
IE 6 features an inadequate definition of third party cookies.
If your site is hosted on server A and your PHP stuff is coming in a framesetting from server B your setcookie-attempts will be blocked when default privacy settings are deployed. Your secondparty-cookie will be regarded as a thirdparty-cookie.

So what you do is not read the P3P-Internet Explorer 6-manual at MS but send a header like

When "setcookie" is passed an empty value (ie, ''), it changes the value to the string "deleted" and sets the date to exactly one year and one second in the past, ignoring the expiration parameter.*

So, I'm guessing that if a client machine has its time set to more than a year in the past or if the browser is somehow broken, then a site visitor could potentially send a PHPSESSID with a value of "deleted". This will cause PHP to create a "sess_deleted" file in the sessions directory.

In my case, I was seeing several incidents per minute, with each user clobbering the other's session data causing all kinds of security and identity issues. Two changes seemed to have solved the problem:

1) Use session_id() in place of '' in setcookie, as well as pick a date that's far in the past (in this case Jan 1, 1970, 8:00:01AM):

setcookie(session_name(), session_id(), 1, '/');

2) Use session_regenerate_id() when logging a user in or otherwise changing their authority level.

Hope this helps somebody.

Rob

* Here is the relevant code in head.c:

if (value && value_len == 0) { /* * MSIE doesn't delete a cookie when you set it to a null value * so in order to force cookies to be deleted, even on MSIE, we * pick an expiry date 1 year and 1 second in the past */ time_t t = time(NULL) - 31536001; dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, t, 0 TSRMLS_CC); sprintf(cookie, "Set-Cookie: %s=deleted; expires=%s", name, dt);

If you experience problems on Microsoft Information Server (IIS) when setting a cookie via PHP and when PHP is running as a CGI binary it is not setting the cookie. After spending many hours on what the problem is here is what happens:

When you invoke setcookie and redirect to another page you will not have your cookie set, because it seems that IIS doesn't set the cookie unless you actually send some contents to the browser. Therefore if you want to set a cookie and then redirect to another page you will have to do the redirection via JavaScript and/or HTML if you want your script to work on IIS.

Observed: session cookies were expiring even though the session was still active. (To test, set a cookie expiry of 5 seconds and keep hitting the page every second. The session will expire and create a new SESSID after 5 seconds despite the fact that you hit the page only a second ago.)

Calling this function before starting the session fixed it. It copies the cookie contents back to itself while forcing an update to the expiry time in the cookie.