Overview of This Lesson

Refresh this page because I am probably still making changes to it.

In this lesson we learn how we can use PHP Sessions to remember data between request-response cycles and why this is important.

Resources

The PHP Manual has a nice page with everything you would want to know about sessions in PHP.

Introduction to PHP Sessions

HTTP is stateless. When you make a request, the request is sent to the server and then the connection is terminated. When the response is sent back, it is sent from the server to the client, and the connection is again terminated. HTTP doesn't "remember" anything about previous requests and responses: When you click a link on a page, the server doesn't remember any of your previous requests or information about those requests. This is unlike FTP (File Transfer Protocol, which you might have used if you've ever uploaded/downloaded files using a client such as FileZilla or CoreFTP), which is stateful. FTP maintains the connection between the client and the server and keeps track of state information about the connection.

server doesn't remember you between request/response cycles
HTTP is Stateless: the server doesn't remember you between request/response cycles

The problem with a stateless protocol like HTTP is that you (as a developer) often need to keep track of information about the user/client between requests. For example, if your site is an online store, you need to keep track of what items the user adds to their shopping cart as they navigate from one page to another. Each time the user requests a new page, how does the server "remember" what items the user already had in their cart?

One way to remember this kind of information is by using cookies. Cookies are permanent but they can only store small amounts of text data. Additionally, many more savvy users block cookies in their browser, as a privacy measure.

Another option many PHP developers prefer are sessions.

A session is a visit to a web site or application: A session consists of a user first loading your site/application, using and/or navigating around the site/application, and then leaving the site/application.

A Session begins when a user accesses your application (any page, generally). A Session ends when one of the following happens:

When a Session is first created, a unique session ID is generated for that session. The server stores the session ID along with any other user data that was included in the request. The server then sends the session ID back to the client in the response. The client reads the session ID and stores it in as a session cookie.

new session starts when request is first made, server generating a unique session id, sending it back to client in the response
The server generates a unique session ID which is stored as a session cookie on the client machine

For the next request, and all subsequent requests, the session id stored in the session cookie is sent along in the request object. The server then reads the session ID in the request and matches it to table of session data it has: the session data with the same session ID belongs to that specific user during this current session. Any new data can be added and associated with that same session ID as neeeded.

the second and subsequent requests sending the session id to the server, server looks up the session id to access stored user data
Every request sends the session ID to the server so the server can look up the user's stored data for that session.

When the session expires or is terminated, the server deletes the stored session data and releases the session ID and its resources. After this occurs, the server doesn't remember the user or any of the stored data.

A developer can use a session variable to keep track of information as the user navigates around the site, making different requests of the server. For example, as the user shops around on your store's site, session variables can be used to remember the items in a shopping cart. When the user navigates to a new page, that page is requested using a new HTTP connection: the page's code can use a special session ID to add, read, and edit session variables stored on the server.

Sessions can somtimes be more advantageous than regular cookies: Cookies are stored on the user's computer, and many users not wishing to have their privacy violated will configure their browser to refuse cookies but still allow session cookies (although you will still have to add fallback code if the user has chosen to block all cookies).

Additionally, cookies can only store text data and to a maximum of 4096 bytes (that includes the cookie name, expiry date, the cookie's value, etc). PHP Sessions don't have a maximum size, and can contain text, numbers, arrays, or entire objects. However, the server running the PHP scripts does have a configuration option called memory_limit, which defines the maximum amount of memory allocated to a running script; the default value is 128MB so clearly you wouldn't want to store anything in a session that's close to 128MB in size.

In PHP, session information is stored in the global variable called $_SESSION. $_SESSION is an associative array where keys reference objects and values that you can add, edit, and remove.

You programmatically start a session when the user visits one of your pages, and the session ends when they leave your page, although you can also programmatically remove data from the session and/or end the session.

Creating a Session

The first thing that you need to do if you want to store and access session data is begin a session. This needs to be done on every page of your site that is going to use the session data.

To start a session, we invoke the session_start() function. The session_start() function will:

The session_start() function call must be the first line of PHP code in your page, and must even go above the HTML <!DOCTYPE> declaration.

<?php
    session_start();
?>
<!DOCTYPE>
<html>
  <head>
  .. etc...

Furthermore, the call to session_start() must be in every single page on your site that uses the session variables.

Each session is assigned a unique Session ID. This identifies each session as unique to a single user. session_start() checks to see if a session with a specific session ID already exists or not. It generates a new session ID if it needs to create a new sessions.

When a session is created and when data is added to the session, the $_SESSION global associative array is automatically populated with any session data stored on the server.

Adding and Reading Session Data

Once you have started or resumed a session, you can add data to it. You simply make up a key and store your data as the value in the $_SESSION variable. You can then read it back using the same key:

<?php
    session_start();

    $_SESSION["example1"] = "Hello, World!";
?>
<!DOCTYPE>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Sessions Examples</title>
  </head>
  <body>
    <h1>Sessions Examples</h1>
    <div><?php echo $_SESSION["example1"] ?></div>
  </body>
  </html>

Note that you'll get an error if you try to access a session key that doesn't exist:

<?php
    session_start();

    // -- code to show error messages:
    ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
    error_reporting(E_ALL);
    // -------------

    $_SESSION["example1"] = "Hello, World!";
?>
<!DOCTYPE>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Sessions Examples</title>
  </head>
  <body>
    <h1>Sessions Examples</h1>
    <div><?php echo $_SESSION["example1"] ?></div>
    <div><?php echo $_SESSION["example2"] ?></div>
  </body>
  </html>

When you load this page, you'll see an error on your page similar to the one below (obviously my path and line # might be different from yours):

Notice: Undefined index: example2 in C:\Users\Wendi\Syst10199\projects\PHPExamples\index.php on line 14

In an earlier lesson, we learned the isset() function. We can use that to see if a session variable was set or not. If a session variable was not set, it means it doesn't yet exist (perhaps this is the user's first visit in the session).

<?php
    session_start();

    // -- code to show error messages:
    ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
    error_reporting(E_ALL);
    // -------------

    $_SESSION["example1"] = "Hello, World!";
    $ex2 = isset($_SESSION["example2"]) ? $_SESSION["example2"] : "no data set";
?>
<!DOCTYPE>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Sessions Examples</title>
  </head>
  <body>
    <h1>Sessions Examples</h1>
    <div><?php echo $_SESSION["example1"] ?></div>
    <div><?php echo $ex2 ?></div>
  </body>
  </html>

In the code above, we've added a line of code (line 4) that checks to see if $_SESSION["example2"] exists. If it does, we store that session variable in the scalar variable $ex2. If the $_SESSION["example2"] session variable doesn't exist, we store the string literal "no data set" in the $ex2 variable. When you load the page, you'll see "no data set" echoed onto the screen, because we've never created the example2 session variable.

Try adding some code at the bottom of the page that assigns a value to the example2 session variable, then reload the page and see if that value outputs onto the screen.

You can modify a session variable any time using an assignment statement, e.g. $_SESSION["example1"] = "Bye";

Exercise/Demonstration

Try this demonstration and exercise to help you understand how session work in PHP. We'll store a variable called "username" in the session, but we'll also use a form to store a "username" variable in the query string, too. Create a new project with two files: index.php and page2.php. Copy and paste the following content in each:

index.php File:

<?php
// TODO 1a: start the session

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
          
// TODO 3: if there is a username in the query string, 
// store it in the session
?>
          
<!doctype html>
<html lang="en">
          
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>PHP Sessions</title>
</head>
          
<body>
  <header>
    <h1>PHP Sessions</h1>
  </header>
          
  <main>
                  
    <!-- TODO 4a: display user name, or Guest -->
    <h2>Welcome, !</h2>
          
    <!-- TODO 4b: display the username value in both the $_GET and $_SESSION -->
    <p>Query String username value: </p>
    <p>Session username value: </p>
          
    <p><a href="page2.php">Page 2</a></p>
          
    <!-- TODO 2a: 
    if there's a username in the session, display 
    the paragraph 
    -->
    <p>Thank you for your return visit!</p>
                  
    <!-- TODO 2b: otherwise, display a form asking for the 
    user name -->
           
    <form>
      <p><label for="username">User Name:
        <input type="text" id="username" name="username">
        </label>
      </p>
      <p><input type="submit"></p>
    </form>
       
  </main>
          
  <footer>
    <address>&copy; 2023 Your Name</address>
    <nav>
      <a href="https://terminallearning.com">Terminal Learning</a>
    </nav>
  </footer>
</body>
</html>

page2.php:

<?php
// TODO 1b: start the session

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
?>
  
<!doctype html>
<html lang="en">
  
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>PHP Sessions Page 2</title>
</head>
  
<body>
  <header>
    <h1>PHP Sessions: Page 2</h1>
  </header>
  
  <main>

    <!-- TODO 4c: display the username value in both the $_GET and 
    $_SESSION (same code from index.php) -->
    <p>Query String username value: </p>
    <p>Session username value: </p>

  </main>
  <footer>
    <address>&copy; 2023 Wendi Jollymore</address>
    <nav>
      <a href="https://terminallearning.com">Terminal Learning</a>
    </nav>
  </footer>
</body>
</html>

Once you've copied and pasted the code, let's start completing the various TODO's that have been left for you:

  1. Add the session_start() function to both pages.
    • Sessions will not work unless the session_start() function is called at the top of each page that requires access to the $_SESSION[] array and other session functions.
    • Upload your project and test out the index page: View the cookies for this page: you'll see a cookie has been set under the domain you're using to test your project. If you're able to view the cookie, you will see it's called PHPSESSID. If you're able to view its value, you'll see it's a long string of what looks like random characters: that's the session ID!
    • If you delete the cookie, and then reload the page, you'll notice that it is re-created with a different ID! When you added session_start(), it looked for a session ID in the request. When it doesn't find one, it creates and new one and sends it back in the response, causing your browser to create a new session cookie with the session ID.
  2. Add the PHP code that displays the "Thank you" paragraph only if there's a "username" variable in the $_SESSION[]. If there isn't, display the form. Use "alternate syntax": it's easier to edit!
    • Upload and test your page: you should see the form, but no paragraph when you visit the index page.
  3. Add the if-statement near the top of the page that adds the "username" to the $_SESSION if it exists in the query string.
    • There's no action to perform if the "username" doesn't exist in the query string: this is a single-sided if.
    • Re-upload and test your index page: Enter a name in the text box and click the SUBMIT button. You should see the paragraph instead of the form!
  4. Add the code to display either the username from the $_SESSION or the word "Guest" in the level-2 heading. Then add the code that displays the value of the "username" variable from the query string in the first paragraph (if it doesn't exist in the query string, display "no username in get"), and the value of the "username" variable from the session in the second paragraph (if it doesn't exist in the session, display "no username in session"). You can copy the paragraphs into page2.php where you see step 4c.
    • Make sure you use isset() - if you try to refer to a variable that doesn't exist in either associative array, you'll get an error. You can use the conditional operator (?:) in a PHP echo tag: it's easier!
    • Upload both pages to the server.
    • Delete the session cookie before you reload the index page!
    • Make sure there's no query string in the URL when you reload!!!
    • After reloading, You'll see "Guest" in the welcome heading, you'll also see that there is no "username" in the query string or the session, and you'll see the form.
    • Enter a name and press SUBMIT: you'll see the username in the welcome heading, and you'll see the username in the paragraphs. You should not see the form.
  5. Click on the Page 2 link: you should see no value for "username" in the query string, although you'll see the username in the session. Why do you not see the username in the query string?

index.php:

<?php
// TODO 1a: start the session 
session_start();

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// TODO 3: if there is a username in the query string, 
// store it in the session
if (isset($_GET["username"])) {
    $_SESSION["username"] = $_GET["username"];
}
?>

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>PHP Sessions</title>
</head>

<body>
  <header>
    <h1>PHP Sessions</h1>
  </header>

  <main>
    <!-- TODO 4a: display user name, or Guest -->
    <h2>Welcome, <?= (isset($_SESSION["username"])
        ? $_SESSION["username"] : "Guest") ?>!</h2>

    <!-- TODO 4b: display the username value in both the $_GET and $_SESSION -->
    <p>Query String username value: <?= (isset($_GET["username"])
        ? $_GET["username"] : "no username in get") ?></p>
    <p>Session username value: <?= (isset($_SESSION["username"])
        ? $_SESSION["username"] : "no username in session") ?></p>

    <p><a href="page2.php">Page 2</a></p>

    <!-- TODO 2a: 
    if there's a username in the session, display 
    the paragraph 
    -->
    <? if (isset($_SESSION["username"])) : ?>
       <p>Thank you for your return visit!</p>

    <!-- TODO 2b: otherwise, display a form asking for the 
    user name -->
    <? else : ?>

      <form>
        <p>
          <label for="username">User Name:
            <input type="text" id="username" name="username">
          </label>
        </p>
        <p><input type="submit"></p>
      </form>
    <? endif; ?>
  </main>

  <footer>
    <address>&copy; 2023 Wendi Jollymore</address>
    <nav>
      <a href="https://terminallearning.com">Terminal Learning</a>
    </nav>
  </footer>
</body>
</html>

page2.php:

<?php
// TODO 1b: start the session 
session_start();
        
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
?>
        
<!doctype html>
<html lang="en">
        
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>PHP Sessions Page 2</title>
  </head>
        
<body>
  <header>
    <h1>PHP Sessions Page 2</h1>
  </header>
        
  <main>
        
    <!-- TODO 4c: display the username value in both the $_GET and 
        $_SESSION (same code from index.php) -->
    <p>Query String username value: <?= (isset($_GET["username"])
        ? $_GET["username"] : "no username in get") ?></p>
    <p>Session username value: <?= (isset($_SESSION["username"])
        ? $_SESSION["username"] : "no username in session") ?></p>
        
  </main>
        
  <footer>
    <address>&copy; 2023 Wendi Jollymore</address>
    <nav>
      <a href="https://terminallearning.com">Terminal Learning</a>
    </nav>
  </footer>
</body>
</html>

Removing Session Variables and Ending Sessions

If you need to, you can remove session variables so that they no longer exist. To remove a session variable, use the unset() function. Pass the function the session variable you want to unset:

unset($_SESSION["example1"]);

To unset all of the session variables, use the session_unset() function:

session_unset();

If you want to end a session, use the session_destroy() function:

session_destroy();

This will destroy the session data for the current session. However, this won't destroy the session cookie on the client machine and won't necessarily destroy any global session variables.

If you want to destroy a session, a better way is to simply delete all the session data manually:

$_SESSION = array();

This still won't delete the session cookie, but that's fine. If you really want to destroy the cookie, check the PHP Manual entry for session_destroy() for some code that deletes the session cookie.

Note that a session will automatically destroy itself a certain amount of time after the user closes the browser, navigates away from your site, or remains inactive for a period of time. You don't necessarily have to end the session unless you want to make sure it ends while the user is still on your site. The amount of time it takes a session to end automatically depends on the server settings: there is an option called "session.gc_maxlifetime" that sets the amount of time a session should stay alive.

Login Demonstration

Try this Login Form Demonstration: it will show you a practical use of sessions and also show you how to log out a user and destroy and existing session. Copy the code below into a new project:

loginForm.php

<!doctype html>
  
<html lang="en">
    
<head>
  <meta charset="utf-8">
  <title>Log In</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="css/main.css">
</head>
    
<body>
  <header>
    <h1>Log In</h1>
  </header>

  <main>

    <div>
    <!-- error messages will eventually go here -->
    </div>
    
    <form action="login.php" method="post">
        
      <p><label for="username">User Name:
        <input type="text" id="username" name="username">
      </p>
      <p><label for="pass">Password:
        <input type="password" id="pass" name="passwd">
      </label></p>
        
      <p><input type="submit"></p>
    </form>
      
  </main>
    
  <footer>
    <address>&copy; thisyear Your Name </address>
  </footer>
</body>
</html>

welcome.php

<!doctype html>
<html lang="en">
  
<head>
  <meta charset="utf-8">
  <title>Welcome</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- assuming you have some CSS files you can use here -->
  <link rel="stylesheet" href="css/main.css">
</head>

<body>
  <header>
    <h1>Welcome</h1>
  </header>
  <main>
      
    <!-- eventually will display user info here -->
  </main>
  
  <footer>
    <address>&copy; thisyear Your Name</address>
  </footer>
</body>
</html>

login.php

<?php 
session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
  
// **NEVER store plain text password data EVER, this is a demo only**
// username => password
$pretendUserData = [
    "foobar" => "password",
    "wendi" => "tunafish", 
    "arti" => "iamboss"
];

// stores potential error messages
$errorMessages = [];
  
// get username and password from query string
$userName = filter_input(INPUT_POST, "username", FILTER_SANITIZE_SPECIAL_CHARS);
$password = $_POST["passwd"];

// if there's no username, that's an error
if (!$userName) {
    $errorMessages[] = "User name is a required field. Please enter your username.";
}
// if there's no password, that's an error	
if (!$password) {
    $errorMessages[] = "Password is a required field. Please enter your password.";
}

// if we have no error messages so far, see if credentials are valid
if (!$errorMessages) {  

    // it's an error if this user doesn't exist in our pretend database
    if (!userExists($userName)) {
        $errorMessages[] = "Sorry, you are not in our database.  Register for an account.";
    // it's an error if the password for this user doesn't match what 
    // we've stored in our pretend database
    } else if (!correctPassword($userName, $password)) {
        $errorMessages[] = "Invalid username or password.";
    } 
}

// if there are any errors, go back to login page
if ($errorMessages) {
    redirectToLogin();
// if there are no errors, move on to welcome page
} else {	
    redirectToWelcome();
}

function redirectToLogin() {
    // back to login page
    // TODO: UPDATE YOUR url
    header("Location: https://fill/this/in/loginForm.php", true, 302);
    exit();
}
// it's tempting to turn redirectToLogin() and redirectToWelcome() into  
// one re-usable function, which would be correct, but these two methods 
// will be doing different things later so just leave it this way
function redirectToWelcome() {
    // go to welcome page
    // TODO: UPDATE YOUR url
    header("Location: https://fill/this/in/welcome.php", true, 302);
    exit();		
}

// returns true if the specified $user exists in our 
// pretend user data
function userExists($user) {
    global $pretendUserData;
    return array_key_exists($user, $pretendUserData);
}

// returns true if the specified $user's inputted $pass matches 
// what is stored in our pretend user data
function correctPassword($user, $pass) {
    global $pretendUserData;
    return $pretendUserData[$user] === $pass;
}
?>

Have a look through the code in each file before continuing. You'll notice I used the header() function in the login.php file. The header() function is used to redirect a request to a different page. Here's how a redirect works:

  1. Your browser sends a request, let's say the request is to foo.php.
  2. The code inside foo.php contains header("bar.php"), so the server sends a response back to the server with either 301 (Moved Permanently, used when the requested resource has been permanently moved to a new file/location) or 302 (Found, similar to 301 except the change is temporary) along with the new file name to request (bar.php).
  3. The client initiates a new request for bar.php
  4. The server receives the request, processes it, and returns bar.php in the response.

The header() function accepts three arguments:

  1. The HTTP header you want to send.
  2. An optional boolean true if you want this header to replace a previous header with the same name, and false if you want to add this header in addition to one that already exists (it's common for some types of headers to have more than one). This is true by default.
  3. An optional response code to use instead of the standard 200 OK.

To use header() for redirecting, just set the Location: header to the URL you want to redirect to.In my example, I just used header("Location: https://.../loginForm.php"). This sends the a response to the client saying that I want it to make a new request to the specified URL.

After you call header(), you must call either the exit() or die() function immediately after. This stops the script from executing any further. Failure to call either exit() or die() after header() will cause problems.

NOTE that you can't send any output (e.g. echo) before you call the header() function, otherwise you'll see the "headers are already sent" error message.

Upload all three files to your server and test them out by loading the loginForm.php page.

Try clicking the SUBMIT button without entering any credentials, and also try it after entering incorrect credentials. You will not see any error messages, even though you can see that your code is validating and recording error messages: we haven't displayed these on the screen yet. You can see I've left a spot for them in the loginForm.php page's code.

Now try logging in with a set of correct credentials (the list of credentials is in the $pretendUserData array in the login.php file).

Notice that after logging in, you only see the Welcome heading, and nothing else: eventually we'll add some more content here that includes the user's name.

Let's modify the example to make it use sessions so we can display error messages and the user's information.

  1. Add the code to each of the 3 files to initiate/continue a session. Use session_start(). Go back through your notes if you can't remember where it goes.
  2. When there are errors, we are redirecting back to the loginForm.php file. We would like to be able to display the error messages on that page:
    • Add a statement above the header() function inside redirectToLogin() that stores the array of error messages in a session variable called "errorMessages". You'll need to also pass the array of error messages into the function.
    • On the loginForm.php page, add the code that displays all the error messages inside the marked <div> element (the one right above the form). Make sure you check to make sure the "errorMessages" variable exists before iterating through it.

    A this point, you can upload your files and test out the login again: try no credentials, a bad username, and a correct username with a bad password. You should see error messages on the page above the form.

  3. When the user successfully logs in, we can display their username on the Welcome page. This is very similar to what we did in the previous demonstration, so this should be simple:
    • In the redirectToWelcome() function, add the statement that adds the username to the "username" session variable. You'll have to pass the username into the redirectToWelcome() function.
    • On the welcome.php page, display any kind of greeting to the user (using their specific username) in a level-2 heading inside the <main> element.

    Re-upload your files and test your changes, although you should delete the session cookie and then restart with a correct login to avoid any problems. Once you log in, you should be presented with the Welcome page showing your username that you used to log in.

Now let's add a Log Out function to our site. Let's add a log-out link to the Welcome page. When the user clicks the link, we'll call a logout.php file:

<p><a href="logout.php">Log Out</a></p>

Now add the logout.php file to your project:

<?php
// we need this so we can access the current session 
// and its data
session_start();

// clear the session array
$_SESSION = array();
        
// add errorMessages with one element:
// why? we're going back to the loginForm page, so
// this will display in the DIV above the form, how nice!
$_SESSION["errorMessages"] = ["You have logged out."];
        
// redirect to the loginForm.php page
header("Location: loginForm.php");
?>

In this code, we're doing the following things:

Upload the new logout.php file and any other files you've changed. Then delete the session cookie and start over by logging in with valid credentials. After you see the welcome page, click the Log Out link: you should see the "you have logged out" mesage above the login form.

Notice that your session cookie is still there and has the same ID: we haven't truely ended the session, just "started over". To truely end the session, you need to delete the session cookie. To do this, you can use setcookie("PHPSESSID", time() - 3600); This will set the PHPSESSID's expiry time to one hour ago, resulting in an expired session cookie. Feel free to experiment with it!

Final version of all files, in case you get stuck:

loginForm.php

<? 
  session_start();
  $errors = $_SESSION["errorMessages"];
?>
<!doctype html>

<html lang="en">
  
<head>
  <meta charset="utf-8">
  <title>Log In</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="css/main.css">
</head>

<body>
  <header>
    <h1>Log In</h1>
  </header>

  <main>

    <div>
    <!-- error messages will eventually go here -->
    <?if ($errors) {
      foreach ($errors as $msg) {
        echo "$msg<br>";
      }
    }?>
    </div>
  
    <form action="login.php" method="post">
      
      <p><label for="username">User Name:
        <input type="text" id="username" name="username">
      </p>
      <p><label for="pass">Password:
        <input type="password" id="pass" name="passwd">
      </label></p>
      
      <p><input type="submit"></p>
    </form>
    
  </main>
  
  <footer>
    <address>&copy; 2017 Wendi Jollymore</address>
  </footer>
</body>
</html>

welcome.php

<?php 
  session_start();
  $username = $_SESSION["username"];
?>
<!doctype html>
  
<html lang="en">
  
<head>
  <meta charset="utf-8">
  <title>Welcome</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- assuming you have some CSS files you can use here -->
  <link rel="stylesheet" href="css/main.css">
</head>

<body>
  <header>
    <h1>Welcome</h1>
  </header>

  <main>
    <!-- eventually will display user info here -->
    <h2><?= $username ?></h2>
    <p><a href="logout.php">Log Out</a></p>
    
  </main>
  
  <footer>
    <address>&copy; 2017 Wendi Jollymore</address>
  </footer>
</body>
</html>

login.php

<?php 
session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
  
// **NEVER store plain text password data EVER, this is a demo only**
// username => password
$pretendUserData = [
    "foobar" => "password",
    "wendi" => "tunafish", 
    "arti" => "iamboss"
];

// stores potential error messages
$errorMessages = [];
  
// get username and password from query string
$userName = filter_input(INPUT_POST, "username", FILTER_SANITIZE_SPECIAL_CHARS);
$password = $_POST["passwd"];

// if there's no username, that's an error
if (!$userName) {
    $errorMessages[] = "User name is a required field. Please enter your username.";
}
// if there's no password, that's an error	
if (!$password) {
    $errorMessages[] = "Password is a required field. Please enter your password.";
}

// if we have no error messages so far, see if credentials are valid
if (!$errorMessages) {  

    // it's an error if this user doesn't exist in our pretend database
    if (!userExists($userName)) {
        $errorMessages[] = "Sorry, you are not in our database.  Register for an account.";
    // it's an error if the password for this user doesn't match what 
    // we've stored in our pretend database
    } else if (!correctPassword($userName, $password)) {
        $errorMessages[] = "Invalid username or password.";
    } 
}

// if there are any errors, go back to login page
if ($errorMessages) {
    redirectToLogin($errorMessages);
// if there are no errors, move on to welcome page
} else {	
    redirectToWelcome($userName);
}

function redirectToLogin($errorMessages) {
    // back to login page
    $_SESSION["errorMessages"] = $errorMessages;
    // TODO: UPDATE YOUR url
    header("Location: https://jollymor.dev.fast.sheridanc.on.ca/examples/w2week11/loginForm.php", true, 302);
    exit();
}
// it's tempting to turn redirectToLogin() and redirectToWelcome() into  
// one re-usable function, which would be correct, but these two methods 
// will be doing different things later so just leave it this way
function redirectToWelcome($userName) {
    // go to welcome page
    $_SESSION["username"] = $userName;
    // TODO: UPDATE YOUR url
    header("Location: https://jollymor.dev.fast.sheridanc.on.ca/examples/w2week11/welcome.php", true, 302);
    exit();		
}

// returns true if the specified $user exists in our 
// pretend user data
function userExists($user) {
    global $pretendUserData;
    return array_key_exists($user, $pretendUserData);
}

// returns true if the specified $user's inputted $pass matches 
// what is stored in our pretend user data
function correctPassword($user, $pass) {
    global $pretendUserData;
    return $pretendUserData[$user] === $pass;
}
?>

logout.php

<?php
// we need this so we can access the current session 
// and its data
session_start();

// clear the session array
$_SESSION = array();

// add errorMessages with one element:
// why? we're going back to the loginForm page, so
// this will display in the DIV above the form, how nice!
$_SESSION["errorMessages"] = ["You have logged out."];

// redirect to the loginForm.php page
header("Location: loginForm.php");
?>

Exercises

1. Add a file sessionTest1.php to your project and paste in the following code:

<?php
session_start();
$random = isset($_GET["random"]) ? htmlentities($_GET["random"]) : 0;
$cancel = isset($_GET["cancel"]) ? htmlentities($_GET["cancel"]) : "no";

if (!isset($_SESSION["test"])) {
    echo "<p>No session found - starting a session now.</p>";
    $_SESSION["test"] = $random;   
} else {
    echo "<p>Session found: " . $_SESSION["test"] . "</p>";   
}
if ($cancel == "yes") {
    echo "<p>Clearing Session...</p>";
    session_destroy();
}
echo "<p><a href='sessionTest1.php?random=".rand(1,10000)."&cancel=no'>Reload this page</a></p>";
echo "<p><a href='sessionTest1.php?cancel=yes'>Destroy session</a></p>";
?>

2. Add a second page to your project called sessionTest2.php. Add the following code:

<?php
session_start();
$cancel = isset($_GET["cancel"]) ? htmlentities($_GET["cancel"]) : "no";
?>

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">

        <title>Exercise 2</title>
    </head>
    <body>

        <?php
            //retrieve session data
            echo "<p>Pageviews=" . $_SESSION['views'] . "</p>";
        ?>
        
        <h1>Exercise 2</h1>
        
        <?php
        if (isset($_SESSION['views']))
            $_SESSION['views'] = $_SESSION['views'] + 1;
        else
            $_SESSION['views'] = 1;
        
        echo "<h2>Same Page</h2>";
        echo "<p>Views=" . $_SESSION['views'] . "</p>";
        
        if ($cancel == "yes") {
            echo "<p>Clearing Session...</p>";
            session_destroy();
        }
        
        echo "<p><a href='sessionTest2.php'>Reload this page</a></p>";
        echo "<p><a href='sessionTest2.php?cancel=yes'>Destroy session</a></p>";
    ?>
    </body>
</html>

3. Add a new HTML file to your project called sessionTest3.html and paste the following into the BODY element:

<p>Passing values from JS to PHP<p>
<script type="text/javascript">
  width = screen.width;
  height = screen.height;
  if (width > 0 && height > 0) {
      window.location.href = "sessionTest3.php?width=" + width + 
        "&height=" + height;
  } else
      exit();
</script>

Now add a PHP file and call it sessionTest3.php. Add the following code:

<?php
session_start();
$width = isset($_GET["width"]) ? htmlentities($_GET["width"]) : 0;
$height = isset($_GET["height"]) ? htmlentities($_GET["height"]) : 0;

if ($width >= 0) {
    $_SESSION['width'] = $width;
}
if ($height >= 0) {
    $_SESSION['height'] = $height;
}
echo "<h1>Screen Resolution:</h1>";
echo "Width: $width<br>";
echo "Height: $height<br>";
?>

Now return to your sessionTest2.php file and add the following code on line 30:

echo "<p>" . $_SESSION["width"] . " x " . $_SESSION["height"] . "</p>";

4. Add new new pages to your project: sessionTest4a.php and sessionTest4b.php. Each file should have the following content:

// sessionTest4a.php:
<?php
    session_start();
    
    $reset = isset($_GET["reset"]) ? htmlentities($_GET["reset"]) : "false";
    if ($reset) {
        session_destroy();
    }
    
    $name = isset($_SESSION["userName"]) ? htmlentities($_SESSION["userName"]) : "";
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">

        <title>Example 4</title>
    </head>
    <body>
        <h1>Example 4</h1>
        
        <form method="post" action="sessionTest4b.php">
            <input type="text" name="txtName" placeholder="Enter your name."
            value='<?=$name?>'>
            <input type="submit">
            <a href="sessionTest4a.php?reset=true">Log Out</a>
        </form>
    </body>
</html>
// sessionTest4b.php:
<?php
    session_start();
    $name = isset($_POST["txtName"]) ? htmlentities($_POST["txtName"]) : "";
    if (!empty($name)) {
        $_SESSION["userName"] = $name;
    }
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">

        <title>Example 4</title>
    </head>
    <body>
        <h1>Example 4</h1>
        
        <?php 
        if (!empty($name)) {
            echo "<h2>Welcome, $name!</h2>";
        } else {
            echo "<h2>Welcome!</h2>";
        }
        ?>
        
        <a href="sessionTest4a.php">Back to First Page</a>
    </body>
</html>

5. Now that you've completed each exercise, add the following statement to sessionTest4b.php in the body of the document after the if/else blocks:

var_dump($_SESSION);

6. Create a simple page that lets you manage your session variables. Provide a list of check boxes for each session variable that currently exists so you can check off which ones you want to delete, and some input fields where you can add a new session variable.

Very simple UI for Session Variables
Select variables to remove and/or add a new session variable
After clicking SUBMIT on previous screen.

Tips: