PHP Cookies And Sessions

php cookies

So we’ve taken a look at how you can pass data in PHP. When dealing with URLs and Links, we’re typically working with data by way of the $_GET super global array. If on the other hand we need to process data that has been submitted via an HTML form, this is typically done with some form of $_POST super global processing. There is another way to work with variable data, and that is by using cookies and sessions. These two techniques are immensely helpful for many reasons. One of the most important is maintaining state. As we learned about in our fun lesson about http status codes, http is a stateless protocol. This means it does not maintain a memory so to speak of each request response cycle. By using sessions and cookies, this can be overcome and web applications can be better customized to the user. Let’s jump in!


The Importance of Cookies

Cookies as you likely know are small bits of data that get stored in your web browser. This is what helps to store a users state. This allows the site to identify the user and recall a specific action they have taken on the page. Cookies are also used to identify when many HTTP requests are made by the same user. You might think an IP address would provide this ability to determine uniqueness, but this is not the case. Think of the thousands of users that are sitting behind a company firewall or NAT Network Address Translation device. All of those users are going to be making requests from the same exact IP address. Cookies are able to bring in a sense of consistency. Now cookies rely on the HTTP protocol to even be possible. They piggyback on the request response cycle. Web servers can not set or read cookies until a request is actually made.

Example Request Response

GET /thepage.php HTTP/1.1
Host: www.vegibit.com
Accept: */*
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: user_id=777

Here when the request is made, the sever responds with the page however in the HTTP header it uses the Set-Cookie command to set a cookie on the users browser. The browser then stores that cookie on the local computer for use in the future. Say the user makes another request of a different page on the same site. This time around, when you make the request, the HTTP GET will include any cookies for that site in the HTTP header to the web server. A second request might then look like this.


GET /theotherpage.php HTTP/1.1
Host: www.vegibit.com
Cookie: user_id=777
Accept: */*

Notice how when this request now goes out, the web server will already know that this request is coming from user_id 777. This is how websites remember your user name and so on. Cookies always piggy back on the standard request response cycle. If you’re not rocking a request response scenario, then you’re not working with any cookies. It is because all matter of setting and reading cookies happens in the HTTP headers that get ping ponged back and forth between the web server and the user’s browser. There is no way to set or receive a cookie without either an HTTP request or response happening.


The $_COOKIE Super Global

Just like we learned about with $_GET and _$POST, super global variables store a range of information in an associative array. Of course when dealing with links and URLs we’re talking about $_GET and when dealing with form submissions we’re talking about $_POST. When it’s time to deal with cookies, which remember are part of the HTTP request response cycle, we can then store this information in the $_COOKIE Super Global and it works in a similar way to the others.


Setting Cookie Values

PHP gives us a dedicated function for setting cookies. The signature looks like this.

setcookie($name, $value, $expire)

As we can see the function takes three values. A name, a value, and an expiration. The name and value parameters are the key value pair of the name of the cookie and the value it stores. The last argument deals with the length of time you would like the cookie to persist. So let’s get busy setting some cookies.

The first two arguments are pretty easy to deal with. The third can be a little tricky if you’re not used to it. When setting an expiration time for a cookie, the server needs to send a UNIX Timestamp as the value. The easiest way to do this is to have PHP generate the current time in a UNIX Timestamp, then add the amount of time you’d like that cookie to persist for based on the current time. UNIX Timestamps are precise to the second, so when we add time to the timestamp, it must also be precise to the second. In other words, when adding the length of time to the timestamp, it must be done in seconds. So if you want a cookie to last a week, you need to provide the number seconds in a week, which is 604800. The other way to do this, which is much more common, is to use math to calculate the amount of time you need. This is how we did it above. It helps to talk it out. We have 60 seconds in a minute, times 60 minutes in an hour, times 24 hours in a day, times seven days in a week to arrive at the same 604800.

Note: When this PHP code executes, it will instruct the server to send this cookie in the HTTP Response Header. This is important. Recall that headers are sent before anything else in the page. In the absence of output buffering, this means that any time you would like to set a cookie, you need to do so at the very top of the page so that it is included in the header sent to the client. It is best to use cookies for non sensitive information. Since they are freely viewable and hackable, cookies make sense for simple user experience conveniences, but not for critical pieces of the application.


Reading Cookie Values

It is a little odd that when we talk about cookies, we are talking about them in the plural sense. Why is this a bit odd? It is so because when we want to set and retrieve data out of the $_COOKIE super global, note that it is singular! In any event, let’s try to take a look at the cookie that was set in the prior snippet of code where we set Score to 575.

Ah ha! Here we simply do a pretty print of the $_COOKIE super global, but in more common use cases you would be using the actual key to retrieve the specific value you are looking for. Let’s see an example of user preferences. We’re going to do a few different things in this example. First off, we’re going to set the name, value, and expiration right in the function call itself. We are also going to give these cookies a ridiculously small shelf life, that being 5 seconds. Lastly we’ll use the actual keys of the $_COOKIE Super Global to retrieve values only if they’re present.

First Request Response Cycle

Hi there No Value! – You like things that are No Value! in color as well as to eat No Value! Food!

Hey wait a minute, it looks like either these cookies do not exist, or they are reporting no value within them. Let’s try the same thing again, 4 seconds later.

Hi there Chris – You like things that are Blue in color as well as to eat Italian Food!

There we go, now the values are taking place. It pays to look at the headers to see this in action. This is what happens when loading the page for the very first time in the web browser.

Request

http://localhost/bootstrapsandbox/cookies.php

GET /bootstrapsandbox/cookies.php HTTP/1.1
Host: localhost
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

Response

HTTP/1.1 200 OK
Date: Tue, 14 Oct 2014 16:43:01 GMT
Server: Apache/2.4.4 (Win32) PHP/5.4.16
X-Powered-By: PHP/5.4.16
Set-Cookie: Name=Chris; expires=Tue, 14-Oct-2014 16:43:06 GMT
Set-Cookie: Color=Blue; expires=Tue, 14-Oct-2014 16:43:06 GMT
Set-Cookie: Food=Italian; expires=Tue, 14-Oct-2014 16:43:06 GMT
Content-Length: 100
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

Browser Output

Hi there No Value! – You like things that are No Value! in color as well as to eat No Value! Food!

Now we can load the same page just a couple of seconds later and see the result.

Request

http://localhost/bootstrapsandbox/cookies.php

GET /bootstrapsandbox/cookies.php HTTP/1.1
Host: localhost
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: Name=Chris; Color=Blue; Food=Italian
Connection: keep-alive

Response

HTTP/1.1 200 OK
Date: Tue, 14 Oct 2014 16:48:05 GMT
Server: Apache/2.4.4 (Win32) PHP/5.4.16
X-Powered-By: PHP/5.4.16
Set-Cookie: Name=Chris; expires=Tue, 14-Oct-2014 16:48:10 GMT
Set-Cookie: Color=Blue; expires=Tue, 14-Oct-2014 16:48:10 GMT
Set-Cookie: Food=Italian; expires=Tue, 14-Oct-2014 16:48:10 GMT
Content-Length: 89
Keep-Alive: timeout=5, max=96
Connection: Keep-Alive
Content-Type: text/html

Browser Output

Hi there Chris – You like things that are Blue in color as well as to eat Italian Food!

Great! This really hammers home where cookies fit in during the request response cycle. Note that on the first request response, we do not see the values of the cookies. This is because it is not until at least one request is made that the server can then even set a cookie or cookies in the first place. On the second request response cycle, the request is carrying the cookies to the server in the header. Therefore PHP is able to hook into those cookies on the incoming request, extract the values from them, then send the response. The takeaway: $_COOKIE Super Global holds values from the previous request, it is not change upon setting the cookie. Pretty slick!.


Unsetting Cookie Values

Now that we know how to set cookies and make use of them, let’s explore how to get rid of them using PHP. It’s not quite as simple as using the unset() function that you might try on a standard variable. Think about it, the browser checks for cookies, populates the cookie super global, sends the request to the server, then we unset it. Well, each time the user makes a request, she is going to re send any cookies present right back to the web server. In order to unset a cookie then, we actually want to use setcookie() once again but in a special way.

Now if we comment out the code that set’s our cookies, we still get the value stored in those cookies.

Let’s unset the Name and Food cookies now.

Smashing! By passing in a value of null to the second parameter and a time in the past to the third parameter, we can successfully remove cookies from the user’s browser. Just note that it is the second request where this actually takes effect.


Sessions In PHP

Sessions are really great tools for managing state and they are related to cookies. The key difference is that when you think of a session, you should think server side. Cookies are strictly browser side. A session is a file that is actually stored on the web server. The web server then sends a cookie to the user that references that session file. You see how that works? It’s like a two step process where the file on the server and the cookie in the browser work together to maintain state or share information. There are a few pros and cons to each approach so lets take a look at them.

Session Pros

  • More Storage A cookie can only hold about 4000 characters maximum. You can go further than this as needed with sessions.
  • Smaller Request Sizes By storing the session on the server, there is no need to put all of this data in the cookie itself for every HTTP Request.
  • Hides Data Values You can’t read the value of a session cookie like you can with a standard cookie in the browser.
  • More Secure Since values are hidden, they are less prone to hacking.

Session Cons

  • Slower to access They are a tiny bit slower, however you’ll never notice it. We’re talking milliseconds here.
  • Expire Immediately Upon Browser Close Once a user closes their browser, the session ends.
  • Session Files Accumulate Since sessions don’t really expire, they tend to build up on the web server. They will need to be manually deleted over time.

One thing to be aware of with Sessions in PHP is that the values can be set and retrieved in the same request response cycle. We saw this is not possible by using standard cookies. Why is this? This is because with regular cookies, the web server must reach out to the users browser over HTTP to actually set or get values from cookies. With sessions, this step can be eliminated. PHP and the web server work directly with a session file stored on the web server itself, then a cookie gets sent back to the user with a reference to that file. In many ways, this makes sessions actually easier to use, you don’t have to think as much. In fact, when storing values in the $_SESSION Super Global, all you have to do is make up and names you like for the keys, then assign the values you want as needed. Let’s see an example.

PHP Cookies Vs Sessions Summary

Hopefully after reading this tutorial you have a better understanding of how cookies and sessions work in PHP. The main takeaways are that cookies live on the users browser while session files live on the server file system. Sessions still use cookies, but it is only to provide a PHP Session ID, or a reference to the Session file that lives on the server.