Remembering Users: Working with Cookies in PHP

To set a cookie, use the setcookie() function. This tells a web client to remember a cookie name and value and send them back to the server on subsequent requests. Example 10-1 sets a cookie named userid to the value ralph.

Example 10-1. Setting a cookie

setcookie(‘userid’, ‘ralph’);

To read a previously set cookie from your PHP program, use the $_COOKIE auto­global array. Example 10-2 prints the value of the userid cookie.

Example 10-2. Printing a cookie value

print ‘Hello, ‘ . $_COOKIE[‘userid’];

The value for a cookie that you provide to setcookie() can be a string or a number. It can’t be an array or more complicated data structure.

When you call setcookie(), the response that the PHP engine generates to send back to the web client includes a special header that tells the web client about the new cookie. On subsequent requests, the web client sends that cookie name and value back to the server. This two-step conversation is illustrated in Figure 10-1.

Figure 10-1. Client and server communication when setting a cookie

Usually, you must call setcookie() before the page generates any output. This means that setcookie() must come before any print statements. It also means that there can’t be any text before the <?php start tag in the page that comes before the set cookie() function. Later in this chapter, “Why setcookie() and session_start() Want to Be at the Top of the Page” on page 226 explains why this requirement exists, and how, in some cases, you can get around it.

Example 10-3 shows the correct way to put a setcookie() call at the top of your page.

Example 10-3. Starting a page with setcookie()

<?php

setcookie(‘userid’, ‘ralph’);

?>

<html><head><title>Page with cookies</title><head>

<body>

This page sets a cookie properly, because the PHP block

with setcookie() in it comes before all of the HTML.

</body></html>

Cookies show up in $_COOKIE only when the web client sends them along with the request. This means that a name and value do not appear in $_COOKIE immediately after you call setcookie(). Only after that cookie-setting response is digested by the web client does the client know about the cookie. And only after the client sends the cookie back on a subsequent request does it appear in $_COOKIE.

The default lifetime for a cookie is the lifetime of the web client. When you quit Safari or Firefox, the cookie is deleted. To make a cookie live longer (or expire sooner), use the third argument to setcookie(). This is an optional cookie expiration time. Example 10-4 shows some cookies with different expiration times.

Example 10-4. Setting cookie expiration

// The cookie expires one hour from now

setcookie(‘short-userid’,’ralph‘,time() + 60*60);

// The cookie expires one day from now

setcookie(‘longer-userid’,’ralph’,time() + 60*60*24);

// The cookie expires at noon on October 1, 2019

$d = new DateTime(“2019-10-01 12:00:00”);

setcookie(‘much-longer-userid’,’ralph’, $d->format(‘U’));

The cookie expiration time needs to be given to setcookie() expressed as the num­ber of seconds elapsed since midnight on January 1, 1970. Two things make coming up with appropriate expiration values easier: time() and the U format character of DateTime::format().1 The time() function returns the current number of elapsed seconds since January 1, 1970 (the Unix “epoch”). So, if you want the cookie expira­tion time to be a certain number of seconds from now, add that value to what time() returns. There are 60 seconds in a minute and 60 minutes in an hour, so 60*60 is the number of seconds in an hour. That makes time() + 60*60 equal to the “elapsed  seconds” value for an hour from now. Similarly, 60*60*24 is the number of seconds in a day, so time() + 60*60*24 is the “elapsed seconds” value for a day from now.

The U format character of DateTime::format() tells you the “elapsed seconds” value for the point in time represented by a DateTime object.

Setting a cookie with a specific expiration time makes the cookie last even if the web client exits and restarts.

Aside from expiration time, there are a few other cookie parameters that are helpful to adjust: the path, the domain, and two security-related parameters.

Normally, cookies are only sent back with requests for pages in the same directory (or below) as the page that set the cookie. A cookie set by http://www.example.com/ buy.php is sent back with all requests to the server www.exanple.com, because buy.php is in the top-level directory of the web server. A cookie set by http://www.exam- ple.com/catalog/list.php is sent back with other requests in the catalog directory, such as http://www.example.com/catalog/search.php. It is also sent back with requests for pages in subdirectories of catalog, such as http://www.example.com/catalog/detailed/ search.php. But it is not sent back with requests for pages above or outside the catalog directory, such as http://www.example.com/sell.php or http://www.example.com/users/ profile.php.

The part of the URL after the hostname (such as /buy.php, /catalog/list.php, or /users/ profile.php) is called the path. To tell the web client to match against a different path when determining whether to send a cookie to the server, provide that path as the fourth argument to setcookie(). The most flexible path to provide is /, which means “send this cookie back with all requests to the server.” Example 10-5 sets a cookie with the path set to /.

Example 10-5. Setting the cookie path

setcookie(‘short-userid’,’ralph’,0,’/’);

In Example 10-5, the expiration time argument to setcookie() is 0. This tells the setcookie() method to use the default expiration time (when the web client exits) for the cookie. When you specify a path to setcookie(), you have to fill in something for the expiration time argument. It can be a specific time value (such as time() + 60*60), or it can be 0 to use the default expiration time.

Setting the path to something other than / is a good idea if you are on a shared server and all of your pages are under a specific directory. For example, if your web space is under http://students.example.edu/~alice/, then you should set the cookie path to /~alice/, as shown in Example 10-6.

Example 10-6. Setting the cookie path to a specific directory

setcookie(‘short-userid’,’ralph’,0,’/~alice/’);

With a cookie path of /~alice/, the short-userid cookie is sent with a request to http://students.example.edu/~alice/search.php, but not with requests to other stu­dents’ web pages such as http://students.example.edu/~bob/sneaky.php or http:// students.example.edu/~charlie/search.php.

The next argument that affects which requests the web client decides to send a partic­ular cookie with is the domain. The default behavior is to send cookies only with requests to the same host that set the cookie. If http://www.example.com/login.php set a cookie, then that cookie is sent back with other requests to the server www.example.com—but not with requests to shop.example.com, www.yahoo.com, or www.example.org.

You can alter this behavior slightly. A fifth argument to setcookie() tells the web cli­ent to send the cookie with requests that have a hostname whose end matches the argument. The most common use of this feature is to set the cookie domain to some­thing like .example.com (the period at the beginning is important for older web cli­ents). This tells the web client that the cookie should accompany future requests to www.example.com,shop.example.com, testing.development.example.com, and any other server name that ends in .example.com. Example 10-7 shows how to set a cookie like this.

Example 10-7. Setting the cookie domain

setcookie(‘short-userid’,’ralph’,0,’/’,’.example.com’);

The cookie in Example 10-7 expires when the web client exits and is sent with requests in any directory (because the path is /) on any server whose name ends with .example.com.

The path that you provide to setcookie() must match the end of the name of your server. If your PHP programs are hosted on the server students.example.edu, you can’t supply .yahoo.com as a cookie path and have the cookie you set sent back to all servers in the yahoo.com domain. You can, however, specify .example.edu as a cookie domain to have your cookie sent with all requests to any server in the example.edu domain.

The last two optional arguments to setcookie() affect a cookie’s security settings. A value of true for the sixth argument to setcookie() tells a web client to only return the cookie over a secure connection—one where the URL begins with https. It is still your responsibility to make sure to only call setcookie() like this when the request to the page executing setcookie() is done over a secure connection. But this instructs the client not to send the cookie back over a subsequent request to an inse­cure URL.

Finally, a value of true for the seventh argument to setcookie() tells the web client that this cookie is an HttpOnly cookie. An HttpOnly cookie gets sent back and forth between client and server as usual, but it is not accessible by client-side JavaScript. This can provide some protection from cross-site scripting attacks (described in “HTML and JavaScript” on page 138). Example 10-8 shows a cookie that expires in 24 hours, has no path or domain restrictions, should only be sent back over a secure connection, and is not available to client-side JavaScript.

Example 10-8. Setting a cookie with security parameters

// null for domain and path tell PHP not to put any

// domain or path in the cookie

setcookie(‘short-userid’,’ratph’,0,null, null, true, true);

To delete a cookie, call setcookie() with the name of the cookie you want to delete and the empty string as the cookie value, as shown in Example 10-9.

Example 10-9. Deleting a cookie

setcookie(‘short-userid’,”);

If you’ve set a cookie with nondefault values for an expiration time, path, or domain, you must provide those same values again when you delete the cookie in order for the cookie to be deleted properly.

Most of the time, cookies you set will be fine with the default values for expiration time, path, or domain. But understanding how these values can be changed helps you understand how PHP’s session behavior can be customized.

Source: Sklar David (2016), Learning PHP: A Gentle Introduction to the Web’s Most Popular Language, O’Reilly Media; 1st edition.

Leave a Reply

Your email address will not be published. Required fields are marked *