|
|
 |
setcookie (PHP 3, PHP 4, PHP 5) setcookie -- Send a cookie Descriptionbool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure]]]]] )
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. 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:
As of PHP 4, 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.
All the arguments except the name argument
are optional. You may also replace an argument with an empty string
("") in order to skip that
argument. Because the expire
argument is integer, it cannot
be skipped with an empty string, use a zero (0)
instead. The following table explains each parameter of the
setcookie() function, be sure to read the
Netscape cookie specification for
specifics on how each setcookie() parameter works
and RFC 2965 for additional
information on how HTTP cookies work.
Table 1. setcookie() parameters explained | Parameter | Description | Examples |
|---|
| name |
The name of the cookie.
|
'cookiename' is called as $_COOKIE['cookiename']
| | 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 not set, the cookie will expire at
the end of the session (when the browser closes).
| | 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 domain that the cookie is available.
|
To make the cookie available on all subdomains of example.com
then you'd set it to '.example.com'. The
. is not required but makes it compatible
with more browsers. Setting it to www.example.com
will make the cookie only available in the www
subdomain. Refer to tail matching in the
spec for details.
| | secure |
Indicates that the cookie should only be transmitted over a
secure HTTPS connection. When set to TRUE, the
cookie will only be set if a secure connection exists. The default
is FALSE.
|
0 or 1
|
Once the cookies have been set, they can be accessed on the next page load
with the $_COOKIE or
$HTTP_COOKIE_VARS arrays. Note,
autoglobals
such as $_COOKIE became available in PHP
4.1.0.
$HTTP_COOKIE_VARS has existed since PHP 3. Cookie
values also exist in
$_REQUEST.
Note:
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.
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 users
system. Consider explode() or
serialize() to set one cookie with multiple names
and values.
In PHP 3, multiple calls to setcookie() in the same
script will be performed in reverse order. If you are trying to
delete one cookie before inserting another you should put the
insert before the delete. As of PHP 4, multiple calls to
setcookie() are performed in the order called.
Some examples follow how to send cookies:
Example 1. setcookie() send example |
<?php
$value = 'something from somewhere';
setcookie("TestCookie", $value);
setcookie("TestCookie", $value, time()+3600); setcookie("TestCookie", $value, time()+3600, "/~rasmus/", ".example.com", 1);
?>
|
|
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:
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:
Example 2. setcookie() delete example |
<?php
setcookie ("TestCookie", "", time() - 3600);
setcookie ("TestCookie", "", time() - 3600, "/~rasmus/", ".example.com", 1);
?>
|
|
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:
Example 3. setcookie() and arrays |
<?php
setcookie("cookie[three]", "cookiethree");
setcookie("cookie[two]", "cookietwo");
setcookie("cookie[one]", "cookieone");
if (isset($_COOKIE['cookie'])) {
foreach ($_COOKIE['cookie'] as $name => $value) {
echo "$name : $value <br />\n";
}
}
?>
|
which prints
three : cookiethree
two : cookietwo
one : cookieone |
|
Note:
The following RFC's may also be useful:
RFC 2109 and
RFC 2695
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.
expire is compared to the client's time which can
differ from server's time.
Note:
Microsoft Internet Explorer 4 with Service Pack 1 applied does
not correctly deal with cookies that have their path parameter
set.
Netscape Communicator 4.05 and Microsoft Internet Explorer 3.x
appear to handle cookies incorrectly when the path and time
are not set.
See also header(), setrawcookie()
and the cookies section.
User Contributed Notes
setcookie
terry at scribendi dot com
08-May-2005 10:07
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.
John Hayes
05-May-2005 06:38
If you want your cookie to persist for as long as possible, set expire to 2147483647.
This is 2^31 - 1, or 19 Jan 2038 03:14:07 GMT.
support at duggen dot net
20-Apr-2005 01:21
Addition to "Carl V"s note. Thanks for the note.
Here is a way to delete alle cookies and cookie arrays from your domain.
$cookiesSet = array_keys($_COOKIE);
for ($x = 0; $x < count($cookiesSet); $x++) {
if (is_array($_COOKIE[$cookiesSet[$x]])) {
$cookiesSetA = array_keys($_COOKIE[$cookiesSet[$x]]);
for ($c = 0; $c < count($cookiesSetA); $c++) {
$aCookie = $cookiesSet[$x].'['.$cookiesSetA[$c].']';
setcookie($aCookie,"",time()-1);
}
}
setcookie($cookiesSet[$x],"",time()-1);
}
ru at jnana dot de
09-Apr-2005 03:35
To salagir dot php dot net at public dot salagir dot com
IIRC the underscore is not a valid character for DNS names, only A-Z, 0-9 and '-' are allowed. However most DNS servers won't complain, but you have to be prepared for all kind of errors occuring with a 'my_subdomain' subdomain name. (It might have changed with the new international domain naming conventions such as 'müller.de', though.)
scissorjammer at hotmail dot com
08-Apr-2005 03:18
As per Sijmen Ruwhof's comment:
It's not that the domain requires a dot as much as it requires a fully qualified domain name. Setting it to false is a valid workaround, as it will default to whatever domain the page is being accessed at. If a fully qualified domain name is unavailable, consider editing your hosts file on both the client and server to have a common domain name to use for the cookie.
Carl V
07-Apr-2005 11:29
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).
salagir dot php dot net at public dot salagir dot com
03-Apr-2005 10:21
I want to share a problem that took me one entire day to solve. This isn't about PHP specifically I guess, but the world *need* to know.
If you try to put a cookie (this also apply for a session through cookie) from a subdomain with and /underscore/, like http://my_subdomain.domain.com/ this *won't work* under IE 6 for some reasons. (No problem with Firefox)
Daine Mamacos
30-Mar-2005 11:14
I found with Internet explorer (ver 5 and 6) that I was unable to delete cookies by setting the expiry to 1 (1 second after the epoch). This was causing me headaches because it worked with every other browser except for internet explorer. The solution, though timely and weird, I figured out was that (as far as I can figure) M$ don't consider 1970 the epoch, they consider 1980 the epoch.
Or something like that.
So to expire a cookie on internet explorer you can set the expiry according to the following formula.
//10 years less the 2 yeas which have leap years
(60*60*24*365*10) = 315360000
//add 2 extra days for the missing leap years.
315360000 + (60*60*24*2) = 315532800
So one can use this to expire a cookie:
setcookie("MyCookie", "BLAHBLAH", 315532800, "/");
I found that this number was the minimum I could set it to, one second less, and it would not expire the cookie.
jonathan at jonathanopie dot com
23-Mar-2005 05:00
I've found that when using header("Location: <destination page>") type 302 redirect, that cookie information in the header will be silently dropped if the <destination page> path includes any non-alphanumeric (except the allowed "-" and ".") characters. That had been pointed out above, and is documented with Microsoft as by design...
http://support.microsoft.com/default.aspx?scid=kb;EN-US;316112
...but what is not made clear, is that the rule seems to include file and directory names too!
Also, I've had unpredictable results when the <destination page> filename begins with ANY character other than strictly alphanumeric characters, even the otherwise allowed "-" and "." characters; and/or if the <destination page> is in a different directory.
Alchaemist
14-Mar-2005 06:36
setcookie + header Location + IIS 5 = Trouble
It took me a long time to figure out what was causing a missing cookie in one system while it worked perfectly in another...
See this one: http://support.microsoft.com/kb/q176113/
In short, this WILL NEVER WORK IN IIS 5:
<?php
header("Pragma: no-cache");
header('Location: http://www.example.com/');
setcookie('AA','1',0,'/');
setcookie('BB','2',time() + 24 * 3600,'/');
?>
You will ONLY get the Location Header, everything else will be "cut out" by IIS 5 CGI implementation.
Solutions:
1- Migrate to Apache/IIS6/Whatever
2- Use a Non Parsed Header Script (nph-*.php)
3- Try with header('Refresh: 0; $URL');
I hope this helps somebody not to spend hours knocking his/her head.
Alchaemist
dear_grommet at reverse dot liamtoh dot moc
04-Mar-2005 02:41
When using cookies to store PHP variables with serialize(),
I found that I also needed to use stripslashes().
Here is an example of code that does what the PHP web site
does - remembering your last search options at the top of the
page.
I would initialise my variable $cookie_data to whatever I wanted,
and I use an array, eg:
<?php
$cookie_data['hist_days'] = 15;
$cookie_data['test1'] = "a string test $ ; \" & ";
$cookie_data['test2'] = 0;
$cookie_data_expire = 60 * 60 * 24 * 60;
?>
And then this code, run at the start of the script, after the
session_start(), will store/restore this cookie data...
<?php
if (isset($_SESSION['cookie_data']))
{
$cookie_data = $_SESSION['cookie_data'];
}
else
{
if (isset($_COOKIE['cookie_data']))
{
$string = $_COOKIE['cookie_data'];
$string = stripslashes($string);
$cookie_data = unserialize($string);
}
}
?>
NB. I found that for such a small amount of data, the gzcompress()
made the string bigger.
The idea is that if the $_SESSION data is available, then it takes
precedence, but if not, then it will re-load the last values from a
cookie that was stored (for the last 60 days).
Then you need to get any user changes for any values and copy
them back into the $_SESSION data.
Then set both the $_SESSION and cookie data., eg:
<?php
$cookie_data['test2']++;
$_SESSION['cookie_data'] = $cookie_data;
$string = serialize($cookie_data);
setcookie('cookie_data', $string, time()+$cookie_data_expire, '/');
$_SESSION['cookie_data'] = $cookie_data;
?>
Danny Lin
19-Feb-2005 11:37
I have XP Home and IE6. I tried the example 3:
<?php
setcookie("cookie[three]", "cookiethree");
setcookie("cookie[two]", "cookietwo");
setcookie("cookie[one]", "cookieone");
if (isset($_COOKIE['cookie'])) {
foreach ($_COOKIE['cookie'] as $name => $value) {
echo "$name : $value <br />\n";
}
}
?>
And it worked. However, when I added expiration info, it stopped working. Then, I noticed that it might be related to the time() on my server (hosted in Texas). With the debugging code below, I found out I have to add two hours. (You will need to "fresh" the browser to get the cookies set.)
<?
for ($i = 0; $i < 10; $i++) {
$time[$i] = time();
setcookie("time_report[$i]",$time[$i], $time[$i]+3600*$i);
}
print_r($_COOKIE);
?>
sikon at gorodok dot net
09-Feb-2005 10:13
The documentation says, 'Consider explode() or serialize() to set one cookie with multiple names and values'. It means implode(), of course, since it is implode() that constructs a string from an array, and explode() splits a string into an array.
José Enrique Serrano Expósito
04-Feb-2005 03:36
For listing all the cookies readed in the client machine.- echo sHTTP_COOKIE_VARS();
<?php
function sHTTP_COOKIE_VARS() {
global $HTTP_COOKIE_VARS; $sEcho = '';
$iCookies = 0;
ForEach( $HTTP_COOKIE_VARS As $vIndex => $vValue ) {
$iCookies++;
if( is_array( $vValue ) ) {
foreach ( $vValue as $vIndex2 => $vValue2 ) {
$sEcho .= '$HTTP_COOKIE_VARS[\'<b>'.$vIndex."</b>']['".$vIndex2.'\'] == "'.
$vValue2.'"<br>';
}
} else {
$sEcho .= '$HTTP_COOKIE_VARS[\'<b>'.$vIndex.'</b>\'] == "'.
$vValue.'"<br>';
}
}
$sEcho .= $iCookies.' cookies listed.';
return $sEcho; }
?>
do not spam M. Kristall at MKP
25-Jan-2005 01:18
The "bug" that prevents cookies from working properly with Windows XP and Internet Explorer 6 seems to be a more strict following of the cookie specifications. This part in particular:
Only hosts within the specified domain can set a cookie for a domain and domains must have at least two (2) or three (3) periods in them to prevent domains of the form: ".com", ".edu", and "va.us". Any domain that fails [sic] within one of the seven special top level domains listed below only require two periods. Any other domain requires at least three. The seven special top level domains are: "COM", "EDU", "NET", "ORG", "GOV", "MIL", and "INT".
localhost should not work. Neither should localhost.localdomain. Though, it may be a bug that 127.0.0.1 does not work, even despit the fact that 127.0.0.1 is not a domain name.
glillibridge at yahoo dot com
08-Jan-2005 02:27
mleer at sp dot nl 19-Dec-2002 02:50 had a very similar problem to my own.
My page is being called from a client url as part of a 100% frame so the url would look correct to the user (reason: PR). My cookies stopped working.
mleer suggested sending the following header:
header('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"');
Unfortunately it did not work for me. I found the below header command at http://www.sitepoint.com/article/p3p-cookies-ie6/2
It worked for me.
header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"');
Good luck.
Sijmen Ruwhof
02-Jan-2005 03:41
My experience with setting cookies, a must read for every developer that doenst want to spend his time debugging cookies..
- if your're using windows XP with Internet Explorer, having a local webserver running and you're setting a cookie in you script, don't set the domain name! Use false instead. Windows XP in combination with Internet Explorer (with Firefox your cookie will be set successful) will not set a cookie when the domain name points to localhost. Examples:
<?
setcookie('test', 'value', false, '/', 'localhost', 0); ?>
Someone noted already this bug in WinXP + IE, but said that the domainname should have a dot in it. That is totally untrue (i've tried a domainname with a dot in it that points to 127.0.0.1). I think that the problem persist that the domainname may not be pointing to 127.0.0.1 so the solution would be:
<?php
setcookie('test', 'value', false, '/', false, 0); ?>
- be sure that the 4th argument (path) always ends with a slash '/'
- be sure that the expire time is false or a timestamp, 0 is not the value for a session cookie (false is the value).
-- Sijmen Ruwhof
christophe at publicityweb dot com
27-Dec-2004 12:46
About the IIS bug (cookies removed in CGI if 302 Redirect)
reported by shrockc (2003-12-23), here's the correct URL.
BUG: Set-Cookie Is Ignored in CGI When Combined With Location
http://support.microsoft.com/kb/q176113/
fromphpnet at blaksaga dot com
22-Jun-2004 12:31
Although the documentation says passing an empty string or zero in the case of an integer to ignore an argument, it is incorrect. You will want to pass NULL to bypass integer arguments such as expire or you will wind up with unwanted results.
adam at metrovanlines dot com
23-Mar-2004 06:47
This limitation is mentiones in the <a href=”http://wp.netscape.com/newsref/std/cookie_spec.html”> Netscape HTTP Cookies Preliminary Specification </a> above but I thought it might save someone some time if it was posted here. (I wasted almost a day about it, Serves me right for not RTFMing ...)
There are limitations on the number of cookies that a client can store at any one time. This is a specification of the minimum number of cookies that a client should be prepared to receive and store.
* 300 total cookies
* 4 kilobytes per cookie, where the name and the OPAQUE_STRING combine to form the 4 kilobyte limit.
* 20 cookies per server or domain. (note that completely specified hosts and domains are treated as separate entities and have a 20 cookie limitation for each, not combined)
Servers should not expect clients to be able to exceed these limits. When the 300 cookie limit or the 20 cookie per server limit is exceeded, clients should delete the least recently used cookie. When a cookie larger than 4 kilobytes is encountered the cookie should be trimmed to fit, but the name should remain intact as long as it is less than 4 kilobytes.
apex at xepa dot nl
24-Nov-2003 09:59
[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 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.
Jörg Aldinger
30-Sep-2003 07:13
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).
dave at fubra dot com
09-Sep-2003 03:36
There are several characters that dont work correctly if part of the cookie name, I in particular ran into problems using = as part of the cookie name ie/
setcookie('dE4fR=', $foo);
this was as a result of base64_encode() ing a variable to use as the name. The cookie was being set fine but the = is stored as a little square character in the cookie which prevent proper retreival.
The solution for me was to use md5() instead of base64_encode() but any other method which avoids the = sign should also solve the problem
thomas at proton dot mine dot nu
29-Jun-2003 07:07
Browsers like Opera and Mozilla are told to need the full page loaded to accept cookies (that's what bmatzelle at NOSPAM dot yahoo dot com said).
You can use cookies at reloading pages, however after sending out all headers call exit(); to stop the rest of the script, so the actual page content is not sent out.
soreman at abv dot bg
11-Apr-2003 06:26
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.
neil
20-Jan-2003 03:34
Some versions of IE6, when you drop a non-persistent cookie, handle this incorrectly and instead drop a persistent cookie.
This is not PHP's fault: ) Rather it is a bug in these versions of IE6. I am posting this because people may be programming session IDs and tokens in what they believe to be non-persistent cookies. Specifically, IE6 build 6.0.2800.1106CO (SP1) does this.
IE6, in this case, will make your application insecure. You should notify IE6 users to manually delete their cookies after their session is completed. Will they do this, no. At least you did your part to notify them of the risk.
We found this to be true after an ethical hack which condemned the use of SessionID's in query string, even if the entire session begins, happens, and ends, in https. M$ Proxy Server (here we go with M$ crappy security) writes these session ID's to it's proxy logs. Since Proxy Server is easily comprimised with numerous well known hacks, your sessions can be. I have seen the logs and seen the sessionid's in https.
Unfortunately, these EH fellows are forgetting that most user's systems are less secure and less patched than most ISP's and corporate proxy servers. We are simply moving the vulnerability to the client by using cookies. If it were up to me, I would leave sessionid in query string.
I was proven right in the case with this browser.
thx
Neil
mleer at sp dot nl
19-Dec-2002 05:50
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
header('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"');
before doing the setcookie-thing. This will enable your cookie to survive any IE-6 privacy settings.
You won't do this if you're working for some doubleclick institution, because if you do, you... you...well... you are not a very nice person!
robert at ourwebhome dot com
05-Dec-2001 06:41
Internet Exploer 6 now requires sites that set cookies to have P3P policies.
From the Microsoft page:
"Internet Explorer 6 implements advanced cookie filtering that is based on the Platform for Privacy Preferences (P3P) specification. By default, Internet Explorer 6 blocks third-party cookies that do not have a compact policy (a condensed computer-readable privacy statement) or third-party cookies that have a compact policy which specifies that personally identifiable information is used without your implicit consent. First-party cookies that have a compact policy which specifies that personally identifiable information is used without implicit consent are downgraded (deleted when you close Internet Explorer). First-party cookies that do not have a compact policy are leashed (restricted so that they can only be read in the first-party context)."
See:
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q260971&GSSNB=1
For more about P3P:
http://www.w3.org/P3P/
| |