This chapter describes: What is a Cookie? Sending and Receiving Cookies,
Output Control Functions, Persistent Cookies, and Other Cookie Properties.
Using Cookies
This chapter describes:
- What is a Cookie?
- Sending and Receiving Cookies
- Output Control Functions
- Persistent Cookies
- Other Cookie Properties
What is a Cookie?
Cookie: A small amount of information sent by a Web server to
a Web browser, saved by the browser, and sent back to the server later.
Cookies are transmitted inside the HTTP header.
Cookies move from server to browser, and back to server as follows:
Web Web Local Web Web
Server Browser System Browser Server
Send Receive Save Send back Receive
cookies --> cookies --> cookies --> cookies --> cookies
As you can see from the diagram, cookies are actually saved to the hard disk
of Web browser user's machines. Many users are concerned about this. But I think
it is pretty safe to allow your browser to save cookies.
If you are really concerned, you can change your browser's settings to reject
cookies. But this may cause many Web based applications fail to run on your
browser.
Sending and Receiving Cookies
Cookies are supported in PHP in the following ways:
1. setcookie() - A built-in function that 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 and tags
as well as any whitespace. If output exists prior to calling this function,
setcookie() will fail and return FALSE. setcookie() can be called using the following simple syntax:
bool setcookie(string name, string value)
where "name" is the name of the cookie, and "value" is the value of the cookie.
2. $_COOKIE[] - A pre-defined associate array that stores cookies submitted by the browser.
To demontrate how to send and receive cookies, I wrote the following PHP script page, CookieTest.php:
\n");
print("Cookies added by the server:\n");
print(" $cookieName: $cookieValue\n");
print("\nCookies received by the server:\n");
foreach ($_COOKIE as $k => $v) {
print " $k = $v\n";
}
print "
\n";
?>
I opened this page with IE, I got:
Cookies added by the server:
Cookie_1: My cookie value
Cookies received by the server:
I clicked the refresh button on the IE window, I got:
Cookies added by the server:
Cookie_2: My cookie value
Cookies received by the server:
Cookie_1 = My cookie value
What happened here was that when I opened the page the first time, the server
received no cookie from the browser's request. But my page added one cookie
named as "Cookie_1" to the response.
When I clicked the refresh button, the browser sent my cookie back to
the server in the request. Then my page added another cookie named as
"Cookie_2" in the response.
If I keep clicking the refresh button, more and more cookies would be added
to the request and response.
But there is a limit. The browser will only take up to 20 cookies from one Web server.
Output Control Functions
As you can see from setcookie() definition, the PHP engine provides no buffer for the HTTP response body.
That means as soon the PHP script starts to send output to the HTTP response body, the HTTP header block
will be finalized, and no allowed to change.
But this default behavior can be altered by calling output control functions:
- setcookie() must be called before any output to the HTTP response. The main reason is that
PHP is not buffering the HTTP response. But you can alter this behavior by using ob_*() functions.
- ob_start() - A built-in function that turns on output buffering.
- flush() - A built-in function that flushes out the contents of the output buffer to the HTTP response body.
Of course, default behavior can also be altered by the configuration file, php.ini. Open php.ini and set the following
line:
output_buffering = 4096
The above configuration line tells the PHP engine to turn on output buffering, and set the buffer size to 4096 bytes.
Once "output_buffering" is turned on, you don't have to call ob_start() in your scripts.
To test the PHP engine default behavior, I modified CookieTest.php into CookieOutputBuffer.php:
\n");
print("Adding cookies by the server:\n");
$numCookies = count( array_keys($_COOKIE) );
$numCookies++;
$cookieName = "Cookie_$numCookies";
$cookieValue = "My cookie value";
print(" $cookieName: $cookieValue\n");
setcookie($cookieName, $cookieValue);
print("\nCookies received by the server:\n");
foreach ($_COOKIE as $k => $v) {
print " $k = $v\n";
}
print "\n";
?>
I then opened php.ini and set the following line:
output_buffering = 0
Running IE on CookieOutputBuffer.php gave me this:
Adding cookies by the server:
Cookie_2: My cookie value
Cookies received by the server:
User = Herong Yang
PHP Warning: Cannot modify header information - headers already
sent by (output started at ...\CookieOutputBuffer.php:4) ...
Now I truly beblieve that PHP engine's default behavior is no output buffering. Make sure to change
"output_buffering" back to 4096 before continuing to the next test.
Persistent Cookies
There are two kinds of cookies: persistent cookies and temporary cookies.
A persistent cookie is stored in a file on your computer. It remains
there when you close Internet Explorer. The cookie can be read by the Web site
that created it when you visit that site again.
A temporary or session cookie is stored only for your current browsing session.
It is deleted from your computer when you close Internet Explorer.
The default behavior of setcookie(name,value) is to set a cookie as a temporary cookie.
To set a persistent cookie, we need to add another parameter to the setcookie() function
call as in the following syntax:
bool setcookie(string name, string value, int expire)
where "expire" specifies when this cookie should be expired. If the expiration time is a future
time, like 30 days from today, this cookie will be set as a persistent cookie. Note that "expire"
should be represented in number of seconds since the epoch. The best way to set "expire" is use
the time() function, which represents the current time in number of seconds since the epoch.
Example, 30 days from today can be expressed as "time()+60*60*24*30".
If "expire" is not given, a temporary cookie will be created.
To show you how to set a persistent cookie, and how the cookie is store in a file,
I wrote the following PHP script page, CookiePersisted.php:
\n");
print("Cookies added by the server:\n");
print(" $cookieName: $cookieValue\n");
print(" Expires at: $expiration\n");
print "\n";
?>
I opened this page with IE, I got:
Cookies added by the server:
User: Herong Yang
Expires at: 1134531525
To find out in which file this cookie is stored in my computer,
I clicked at IE "Tools" menu, selected "Internet Options...".
and clicked the "Settings..." button in the "Temporary Internet files" section of the "General" tab.
I saw where is my "Temporary Internet files folder". So I went to that folder,
and saw a cookie file named something like "Cookie:user@localhost/".
I double clicked on that file, and managed to open it in notepad:
User
Herong+Yang
localhost/
1024
3801469056
29753439
3934260416
29747404
*
Actually, I saw a lots of other cookie files created by other Web sites that I have visited in the past.
I deleted all of them.
Other Cookie Properties
A cookie also has two other properties:
1. "domain" - A property that defines the domain of Web servers to which this cookie should be made available.
Web browsers will send a cookie back to a Web server when the Web server matches its defined domain.
Web browsers will never send back a cookie to a domain other than its defined domain.
For example, if a cookie's domain is www.google.com, the browser will send back this cookie to the server
only when the browser is visiting www.google.com. The browser will never send back this cookie to www.yahoo.com.
To make a cookie available for all sub domains of a top level domain, set the domain property
to the top level domain name. For example, if a cookie's domain is set to ".google.com", this cookie will be
available to all google sub domains, like groups.google.com and gmail.google.com.
2."path" - A property that defines a Web server path to which this cookie should be made available.
Web browsers will send a cookie back to a Web server when the Web server matches its defined domain, and
the requested page matches its defined path. Web browsers will never send back a cookie to requested path
other than its defined path.
Note that the defined path also includes all its sub paths. For example, if a cookie's domain is "www.amazon.com",
and path is "/order/", then a browser will send back this cookie for requests like
"http://www.amazon.com/order/checkout.html", and "http://www.amazon.com/order/report/invoice.html".
But a browser should not send back this cookie for requests like "http://www.amazon.com/catelog/book.html".
The setcookie() function offers two more parameters to allow you to set "domain" and "path" properties on a cookie
as in the following syntax:
bool setcookie(string name, string value, int expire, string path,
string domain)
where "path" specifies the cookie's path property, and "domain" specifies the cookie's domain property.
If "path" is not given, the cookie will have "/" as the default path.
If "domain" is not given, the cookie will have the current domain as the default domain.
Okay. Let's play the properties with the following script, CookieProperties.php:
\n");
print("\nAdding a cookie with default properties:\n");
$cookieName = "User";
$cookieValue = "Herong Yang";
$expiration = time()+60*60*24*30;
setcookie($cookieName, $cookieValue, $expiration);
print(" Name: $cookieName\n");
print(" Value: $cookieValue\n");
print(" Expiration: $expiration\n");
print("\nAdding a cookie with non-default properties:\n");
$cookieName = "Book";
$cookieValue = "Herong's Tutorial Notes on PHP";
$expiration = time()+60*60*24*30;
$path = "/";
$domain = "localhost";
setcookie($cookieName, $cookieValue, $expiration, $path, $domain);
print(" Name: $cookieName\n");
print(" Value: $cookieValue\n");
print(" Expiration: $expiration\n");
print(" Path: $path\n");
print(" Domain: $domain\n");
print("\nCookies received by the server:\n");
foreach ($_COOKIE as $k => $v) {
print " $k = $v\n";
}
print "
\n";
?>
Ran this script in IE, I got:
Adding a cookie with default properties:
Name: User
Value: Herong Yang
Expiration: 1134622043
Adding a cookie with non-default properties:
Name: Book
Value: Herong's Tutorial Notes on PHP
Expiration: 1134622043
Path: /
Domain: localhost
Clicked the refresh button on IE, I got:
Adding a cookie with default properties:
Name: User
Value: Herong Yang
Expiration: 1134622059
Adding a cookie with non-default properties:
Name: Book
Value: Herong's Tutorial Notes on PHP
Expiration: 1134622059
Path: /
Domain: localhost
Cookies received by the server:
User = Herong Yang
Apparently, my script did not set the properties correctly. The browser should have sent back my second cookie also.
So either the "path=/" or "domain=localhost" did not match my local IIS environment. I could not figure it out why.
Conclusion
- setcookie() must be called before any output to the HTTP response. The main reason is that
PHP is not buffering the HTTP response. But you can alter this behavior by using ob_*() functions.
- A persistent cookie is stored in a cookie file on the browser's local machine.
- A persistent cookie can have a expiration time to be expressed in number of seconds since epoch.
- Web browser will only send back a cookie when both domain and path match the requested domain and path.
- To make a cookie available for all sub domains of a top level domain, set the domain property
to the top level domain name.
|