PHP State Management (Sessions & Cookies) Tutorial

In this tutorial we learn how to store the state of our PHP application on the user's browser (with cookies), or on the server itself (with sessions).

We also learn the best practice to delete a cookie, and how to test if a cookie can be set.

Here's a table of contents of what you'll learn in this lesson:
(click on a link to skip to its section)

Let's jump right in.

What is state management?

PHP allows us to save certain states of the application either on the server itself, or in the user’s browser. PHP provides us with two different techniques to manage states in a web application:

  1. Sessions: Server Side State Management
  2. Cookies: Client Side State Management

What is a session

Sessions are states that are saved to the server, such as a unique ID, or if a user is logged into their account.

Because sessions are not stored in the browser like cookies, it is a more secure option.

As an example, let’s consider a social media application such as Facebook.

When users log into their Facebook account, the application remembers who they are until they log out. When logged in, a user has access to special features such as sending messages, uploading images and videos, joining groups etc.

The application tracks these states and stores them as a session on the server. As soon as the user is logged out, the session is destroyed.

How to start a session and store session data

To start a session in PHP, we use the session_start() function. We store session data by using the $_SESSION superglobal.

Syntax:
// start a session
session_start();

// set a session variable
$_SESSION["session_variable_name"] = session_variable_value;

The session_start() function must be the first statement in the document.

Example: main.php - start a session and store session data
<?php

// start a session
session_start();

// set a session variable
$_SESSION["username"] = "John";
$_SESSION["userID"] = 1;

?>
<html>
<body>

<a href="sessions.php">Sessions page</a>

</body>
</html>

In the example above, we also create an html hyperlink to another page which, will demonstrate how sessions save data across pages.

How to access session data

Before we access the session data set up in the previous section, create the sessions.php file in your main directory.


  1. Inside Atom, navigate to your PHPProjects folder.
  2. In the Project Pane, right-click on the PHPProjects folder and select New File .
  3. Name the file __sessions.php__ and press Enter or Return on your keyboard.

We access session data in the same way we would access an array element.

Example: sessions.php - access session data
<?php
session_start();

echo "Hello " . $_SESSION["username"];

?>

When we run the main.php file, it stores the session data. Clicking the link takes us to a new page where we display the stored data. The username value survived across pages.

We must remember to start a session with the session_start() function, even on pages that only access session data. The session start function will fetch an ongoing session if one has already been started elsewhere.

How to change session data

Session variables are mutable, which means they can be changed during runtime. To change the value of a session variable, we simply assign a new value to it.

Syntax:
 $_SESSION["session_variable_name"] = "new_value";
Example: main.php - change session data
<?php

// start a session
session_start();

// set a session variable
$_SESSION["username"] = "Jane";
$_SESSION["userID"] = 1;

?>
<html>
<body>

<a href="sessions.php">Sessions page</a>

</body>
</html>

In the example above, we change the username session variable from John to Jane. If we run main.php and click on the link, the new name will be printed to the page.

How to remove stored session data from variables

If we want to clear out all the stored values from session variables, we use the session_unset() function.

Example: session.php - remove stored session data from variables
<?php
session_start();

echo "Hello " . $_SESSION["username"];

// unset username value
session_unset();

// try to print username to the page
echo $_SESSION["username"];

?>

After we unset the value of the username variable, we can no longer print it and the interpreter will raise an Undefined index error.

Output:
 Notice: Undefined index: username on line 10

How to destroy a session

We can destroy a whole session completely with the session_destroy() function.

Example: sessions.php - destroy a session
<?php
session_start();

echo "Hello " . $_SESSION["username"];

// unset username value
session_destroy();

// try to print username to the page
echo $_SESSION["username"];

?>

When the session is destroyed, both echo statements will not be able to print the username variable, and the interpreter will raise an error.

Output:
Notice: Undefined index: username on line 4
Hello
Notice: Undefined index: username on line 10

It’s important to note that destroying a session may take some time, it is not always immediate.

Typically, a session is destroyed after logout or checkout etc. to clean the session variable of the user specific data.

Cookies are states that are saved to the user’s system, instead of the server. Unlike a session, a cookie has a 1024 byte size limit. Cookies are sent to the web server as header information in every HTTP request.

Cookies are not stored on the server, they can be modified and deleted. Cookies are less reliable and secure than sessions.

As an example, let’s consider an application with a member area. Once a user enters their log in details, a cookie is created on that user’s system that saves those details.

If the user comes back to the application, the login details can be automatically filled into the form so that the user doesn’t have to repeat the process.

Cookies are also commonly used to serve advertisements based on products that the user views around the web. For example, if a user views a product on Amazon, they will find advertisements of similar products when using Facebook or Google services.

PHP provides us with the setcookie() function to create, or set, a cookie.

Syntax:
 setcookie(name, value, expiration, path, domain, secure);

The first argument, name, is mandatory for every cookie. The rest of the arguments are optional, but recommended.

ArgumentUsage
nameRequired. The name the cookie will be referred to. Must be a string.
valueOptional. The value of the cookie.
expirationOptional. If an expiration time is not set, the cookie will expire when the browser is closed.
pathOptional. The path on the server the cookie will be available on. The cookie can be set to '/' to be available to the entire domain.
domainOptional. The (sub)domain that the cookie is available to. Sub-domains of the specified domain are automatically included.
secureOptional. If set to true, the cookie will only be set for a HTTPS secure connection.
Example: how to set a cookie
<?php

// Expires when the browser closes
setcookie("UserID", 007);

// Expires in 1 minute (60 seconds)
setcookie("SelfDestructMsg", "1 minute", time()+60)

// Only available to a specific subdomain over HTTPS
setcookie("Name", "Bond, James", time()+60, "/totally_not_cookies/", "agents.mi6.com", 1);

?>

The value portion of the cookie will automatically be urlencoded when the cookie is sent. Characters such as a space and . will be converted to underscores. When the cookie is received, it will be automatically decoded and assigned to a variable with the same name.

The expiration time is often confusing for many beginners that aren’t used to working with the UNIX timestamp. In such a case we can use the strtotime() function which converts time from a string into the correct time.

Syntax:
 strtotime('+30 days')
Example: alternate expiration time
<?php

// Expires in 30 days
setcookie("UserID", 007, strtotime('+30 days'));

?>

We access a cookie’s value via the $_COOKIE superglobal by specifying its name as the key.

Syntax:
 $_COOKIE["cookie_name"];
Example: access a cookie
<?php

setcookie("Name", "Bond, James", time()+60);

echo "Agent: " . $_COOKIE["Name"];

?>

We can change any argument of the cookie, except the name, by assigning a new value. When a new name is assigned, it will create a new cookie instead of changing the current cookie.

Example: how to change cookie data
<?php

setcookie("Name", "Hunt, Ethan", time()+5);

echo "Agent: " . $_COOKIE["Name"];

?>

We delete a cookie by setting its expiration time to anything in the past.

Example: how to delete a cookie
<?php

// Current time - 60 minutes
setcookie("Name", "Hunt, Ethan", time()-3600);

echo "Agent: " . $_COOKIE["Name"];

?>

When a cookie is deleted and we try to access it, the interpreter will raise an Undefined index error.

Output: deleted cookie error
 Notice: Undefined index: Name on line 6

The error is raised as an undefined index because the index Name in the $_COOKIE superglobal doesn’t exist anymore.

There is a risk of the user modifying their system’s time backwards so that the cookie does not expire. We recommend that the cookie be set to expire one second into the future, instead of in the past.

Example: delete a cookie in a second
<?php

// Current time - 60 minutes
setcookie("Name", "Hunt, Ethan", time()+1);

echo "Agent: " . $_COOKIE["Name"];

?>

How to test if cookies can be set

With all the privacy concerns these days, many users disable cookies in their browsers. If we want to know if a cookie can be set in a user’s browser, we have to try and create a cookie. If the attempt is successful, we know that cookies can be set.

Example: test if a cookie can be set
<?php

setcookie("isAllowed", 1);

if(isset($_COOKIE["isAllowed"])) {
    echo "Cookies are allowed";
} else {
    echo "Cookies are not allowed";
}

?>

Summary: Points to remember

  • Sessions saves states to the server and are more secure.
  • Sessions use the $_SESSION superglobal array.
  • Cookies save states to the client’s browser and are less secure.
  • Cookies use the $_COOKIE superglobal array.
  • We can use the strtotime() function for the expiration time to convert a time string into a UNIX timestamp.
  • When deleting cookies, it’s recommended to set the expiration time 1 second into the future instead of the past.
  • Some users might disable cookies in their browser. Test if a cookie can be set before trying to set one.