Part V: User Authentication and Tracking
Chapter 17: Session Basics
Overview
Sessions are like cookies on steroids. Using sessions, you can maintain user-specific information without setting multiple cookies or even using a database. In this chapter, you'll learn how to do the following:
• Start a session
• Add a variable to the $_SESSION superglobal
• Enable a per-user access count
• Maintain user preferences throughout multiple pages Before You Begin...Check php.ini
Before you start working with sessions, check a value in your php.ini file. Look for this section of text and read it carefully:
; Argument passed to save_handler. In the case of files, this is the path
; where data files are stored. Note: Windows users have to change this
; variable in order to use PHP's session functions.
session.save_path = /tmp
To reiterate, you must modify the value of session.save_path so that the file can be written to a directory that exists. This change primarily affects Windows users, and the modification is simple: enter a directory name after the = for session.save_path.
For example, my php.ini file on Windows contains this:
session.save_path = c:\Windows\Temp
After making the change, restart Apache so that the changes take effect. If you are using Linux/UNIX, /tmp is a standard directory, and you can leave this alone unless you want to change it for some compelling reason.
What's a Session?
In terms of time, a session is the amount of time during which a user visits a site. In the programming world, a session is kind of like a big blob that can hold all sorts of variables and values.
• This blob has an identification string, such as 940f8b05a40d5119c030c9c7745aead9.
• This identification string is automatically sent to the user when a session is initiated, in a cookie called PHPSESSID.
• On the server side, a matching temporary file is created with the same name (940f8b05a40d5119c030c9c7745aead9).
Understanding Session Variables
Session variables (and their values) are stored in the temporary session file on the Web server. Since these values and variables are not kept in a database, no
additional system resources are required to connect to and extract information from database tables. You can access session variables through the $_SESSION
superglobal.
For example, a temporary session file might contain the following:
count|s:7:"76";
valid|s:7:"yes";
In this example, count and valid are the names of the session variables and 76 and yes are their respective values. However, to out the variable in the session, you must first explicitly add it to the $_SESSION superglobal. Once it is added, you can extract the value (using $_SESSION[count] or $_SESSION[valid], in this example).
When you attempt to retrieve a session variable, the sequence goes something like this (say you're trying to get the value of $_SESSION[count]):
1. The PHP parser gets the value of PHPSESSID from the user cookie.
2. The PHP parser finds a matching temporary session file.
3. Inside the session file, the PHP parser looks for count and then finds its value (say, 76).
4. $_SESSION[count] is equal to 76.
Next, you'll start your own per-user counter script using a session.
Starting a Session
Starting a session is a snap. You just call the session_start() function, and PHP takes care of the rest—sending the cookie and creating the temporary file.
1. Open a new file in your text editor and start a PHP block:
2. <?
3. Call the session_start() function:
4. session_start();
5.
6.
Note The session_start() function actually performs several important tasks.
First, it checks to see if a session has been started for the current user, and it starts one if necessary. It also alerts the PHP engine that session variables and other session-related functions will be used within the specific script.
Because of the dual purpose of session_start(), use it at the beginning of all session-related scripts.
7. Create a string to hold a message:
8. $msg = "started a session....";
9. Close the PHP block:
10. ?>
11. Type the following HTML:
12. <HTML>
13. <HEAD>
14. <TITLE>Start a Session</TITLE>
15. </HEAD>
16. <BODY>
17. Display the message string:
18. <? echo "$msg"; ?>
19. Add some more HTML so that the document is valid:
20. </BODY>
21. </HTML>
22. Save the file with the name session.php and place this file in the document root of your Web server.
23. Open your Web browser and type http://127.0.0.1/session.php
How inspiring was that? In the next section, you'll register an actual value and watch it change during the course of your session.
Registering and Modifying Session Variables
The goal of this script is to register a variable and change its value during the course of a user session.
1. Open a new file in your text editor, start a PHP block, and call the session_start() function:
2. <?
3. session_start();
4. Register a variable called count:
5. session_register('count');
6.
7.
Note Now, for as long as this session exists, a variable called
$_SESSION[count] will be available. Currently, the variable has no value.
8. Increment the value of $_SESSION[count] to account for the current access:
9. $_SESSION[count]++;
10. Create a string to hold a message, including the value of $_SESSION[count]:
11. $msg = "<P>You've been here $_SESSION[count] times. Thanks!</p>";
12. Close the PHP block and type the following HTML:
13. ?>
14. <HTML>
15. <HEAD>
16. <TITLE>Count Me!</TITLE>
17. </HEAD>
18. <BODY>
19. Display the message string:
20. <? echo "$msg"; ?>
21. Add some more HTML so that the document is valid:
22. </BODY>
23. </HTML>
24. Save the file with the name countme.php and place this file in the document root of your Web server.
25. Open your Web browser and type http://127.0.0.1/countme.php
In the next section, you'll handle more than just an access count: you'll set and display user preferences during a user session.
Managing User Preferences with Sessions
Moving beyond the simple access counter, you can use sessions to manage your users' preferences when they visit your site. In this three-step example, you'll start a session, ask a user for his font family and base font size preferences, display those preferences on subsequent pages, and allow the user to change his mind and reset the values.
Starting a Session and Registering Defaults
In this script, you'll start a session and register the font_family and font_size variables. The displayed HTML will be a form that allows you to change your preferences.
1. Open a new file in your text editor, start a PHP block, and call the session_start() function:
2. <?
3. session_start();
4. Start an if…else block to check for any previous values for font_family and font_size. If values are not present in the current session, assign default values and add them:
5. if ((!$_SESSION[font_family]) || (!$_SESSION[font_size])) { 6. $font_family = "sans-serif";
7. $font_size = "10";
8. $_SESSION[font_family] = $font_family;
9. $_SESSION[font_size] = $font_size;
10.
11. If previous values do exist, extract the values from the $_SESSION superglobal.
12. } else {
13. $font_family = $_SESSION[font_family];
14. $font_size = $_SESSION[font_size];
15. } 16.
Note Since the user will come back to this script to reset his display
preferences, you have to take into account the fact that the values of the variables must always be extracted from the session itself.
If you simply added the variables to a session without checking for previous values, each time the page were loaded the value of these variables would be overwritten as an empty string.
17. Close the PHP block and type the following HTML:
18. ?>
19. <HTML>
20. <HEAD>
21. <TITLE>My Display Preferences</TITLE>
22. Create a style sheet block, starting with the opening <STYLE> tag:
23. <STYLE type="text/css">
24. Add a style sheet entry for the BODY, P, and A tags. Mingle HTML and PHP to display the current values of $font_family and $font_size:
25. BODY, P, A {font-family:<? echo "$font_family"; ?>;font-size:<?
26. echo "$font_size"; ?>pt;font-weight:normal;}
27. Add a style sheet entry for the H1 tag. Mingle HTML and PHP to display the value of $font_family and a modified value of $font_size (base value plus 4):
28. H1 {font-family:<? echo "$font_family"; ?>;font-size:<? echo 29. $font_size + 4; ?>pt;font-weight:bold;}
30. Close the </STYLE> tag and continue with the HTML, adding a heading and beginning a form. Assume that the form method is POST and the action is session02.php:
31. </STYLE>
32. </HEAD>
33. <BODY>
34. <H1>Set Your Display Preferences</H1>
35. <FORM METHOD="POST" ACTION="session02.php">
36. Create a set of radio buttons from which the user can choose a new font family:
37. <P>Pick a Font Family:<br>
38. <input type="radio" name="sel_font_family" value="serif"> serif 39. <input type="radio" name="sel_font_family" value="sans-serif"
40. checked> sans-serif
41. <input type="radio" name="sel_font_family" value="Courier">
42. Courier
43. <input type="radio" name="sel_font_family" value="Wingdings">
44. Wingdings 45. </p>
46. Create a set of radio buttons from which the user can choose a new base font size:
47. <P>Pick a Base Font Size:<br>
48. <input type="radio" name="sel_font_size" value="8"> 8pt
49. <input type="radio" name="sel_font_size" value="10" checked> 10pt 50. <input type="radio" name="sel_font_size" value="12"> 12pt
51. <input type="radio" name="sel_font_size" value="14"> 14pt 52. </p>
53. Add a submit button and close the form:
54. <P><input type="submit" name="submit" value="Set Display 55. Preferences"></p>
56. </FORM>
57. Add some more HTML so that the document is valid:
58. </BODY>
59. </HTML>
60. Save the file with the name session01.php and place this file in the document root of your Web server.
Your entire code should look like this:
<?
//start a session session_start();
//check for stored values and register defaults
if ((!$_SESSION[font_family]) || (!$_SESSION[font_size])) { $font_family = "sans-serif";
$font_size = "10";
$_SESSION[font_family] = $font_family;
$_SESSION[font_size] = $font_size;
} else {
//extract from $_SESSION superglobal if exist $font_family = $_SESSION[font_family];
$font_size = $_SESSION[font_size];
}
BODY, P, A {font-family:<? echo "$font_family"; ?>;font-size:<?
echo "$font_size"; ?>pt;font-weight:normal;}
H1 {font-family:<? echo "$font_family"; ?>;font-size:<? echo
$font_size + 4; ?>pt;font-weight:bold;}
</STYLE>
</HEAD>
<BODY>
<H1>Set Your Display Preferences</H1>
<FORM METHOD="POST" ACTION="session02.php">
<P>Pick a Font Family:<br>
<input type="radio" name="sel_font_family" value="serif"> serif
<input type="radio" name="sel_font_family" value="sans-serif"
checked> sans-serif
<input type="radio" name="sel_font_family" value="Courier">
Courier
<input type="radio" name="sel_font_family" value="Wingdings">
Wingdings
</P>
<P>Pick a Base Font Size:<br>
<input type="radio" name="sel_font_size" value="8"> 8pt
<input type="radio" name="sel_font_size" value="10" checked> 10pt
<input type="radio" name="sel_font_size" value="12"> 12pt
<input type="radio" name="sel_font_size" value="14"> 14pt
</p>
<P><input type="submit" name="submit" value="Set Display Preferences"></p>
</FORM>
</BODY>
</HTML>
Now open your Web browser and type http://127.0.0.1/session01.php.
In the next section, you'll create the script that handles the preference changes.
Making Preference Changes
In this script, you'll assign the new values for font_family and font_size and display a confirmation that the changes have been made.
1. Open a new file in your text editor, start a PHP block, and call the session_start() function:
2. <?
3. session_start();
4. Start an if…else block to check for the posted values for font_family and font_size. If values are present, add them in the session.
5. if (($_POST[sel_font_family]) && ($_POST[sel_font_size])) { 6. $font_family = $_POST[sel_font_family];
7. $font_size = $_POST[sel_font_size];
8. $_SESSION[font_family] = $font_family;
9. $_SESSION[font_size] = $font_size;
10.
11. Continue the block to check for previously stored values for font_family and font_size, but only if the posted values are not present.
12. } else if (((!$_POST[sel_font_family]) &&
13. (!$_POST[sel_font_size])) && ($_SESSION[font_family]) &&
14. ($_SESSION[font_size])) {
15. $font_family = $_SESSION[font_family];
16. $font_size = $_SESSION[font_size];
17. $_SESSION[font_family] = $font_family;
18. $_SESSION[font_size] = $font_size;
19. Finally, if values are not present from the form or from a previous session, define and add some defaults:
20. } else {
21. $font_family = "sans-serif";
22. $font_size = "10";
23. $_SESSION[font_family] = $font_family;
24. $_SESSION[font_size] = $font_size;
25. }
26. Close the PHP block and type the following HTML:
27. ?>
28. <HTML>
29. <HEAD>
30. <TITLE>My Display Preferences</TITLE>
31. Create a style sheet block, starting with the opening <STYLE> tag:
32. <STYLE type="text/css">
33. Add a style sheet entry for the BODY, P, and A tags. Mingle HTML and PHP to display the current value of $font_family and $font_size:
34. BODY, P, A {font-family:<? echo "$font_family"; ?>;font-size:<?
35. echo "$font_size"; ?>pt;font-weight:normal;}
36. Add a style sheet entry for the H1 tag. Mingle HTML and PHP to display the value of $font_family and a modified value of $font_size (base value plus 4):
37. H1 {font-family:<? echo "$font_family"; ?>;font-size:<? echo 38. $font_size + 4; ?>pt;font-weight:bold;}
39.
40. Close the </STYLE> tag and continue with the HTML, displaying the values of the two registered session variables:
41. </STYLE>
42. </HEAD>
43. <BODY>
44. <H1>Your Preferences Have Been Set</H1>
45. <P>As you can see, your selected font family is now <? echo 46. "$font_family"; ?>, with a base size of <? echo "$font_size" ?>
47. pt.</p>
48. Provide a link back to session01.php in case the user wants to change
preferences again, then add some more HTML so that the document is valid:
49. <P>Please feel free to <a href="session01.php">change your 50. preferences</a> again.</p>
51. </BODY>
52. </HTML>
53. Save the file with the name session02.php and place this file in the document root of your Web server.
Your entire code should look like this:
<?
//start a session session_start();
//check for posted values and register defaults
if (($_POST[sel_font_family]) && ($_POST[sel_font_size])) { $font_family = $_POST[sel_font_family];
$font_size = $_POST[sel_font_size];
$_SESSION[font_family] = $font_family;
$_SESSION[font_size] = $font_size;
//check for stored values, extract from $_SESSION superglobal and register
} else if (((!$_POST[sel_font_family]) &&
(!$_POST[sel_font_size])) && ($_SESSION[font_family]) &&
($_SESSION[font_size])) {
$font_family = $_SESSION[font_family];
$font_size = $_SESSlON[font_size];
$_SESSION[font_family] = $font_family;
$_SESSION[font_size] = $font_size;
//register defaults } else {
$font_family = "sans-serif";
$font_size = "10";
$_SESSION[font_family] = $font_family;
$_SESSION[font_size] = $font_size;
}
BODY, P, A {font-family:<? echo "$font_family"; ?>;font-size:<?
echo "$font_size"; ?>pt;font-weight:normal;}
H1 (font-family:<? echo "$font_family"; ?>;font-size:<? echo
$font-size + 4; ?>pt;font-weight:bold;}
</STYLE>
</HEAD>
<BODY>
<H1>Your Preferences Have Been Set</H1>
<P>As you can see, your selected font family is now <? echo
"$font_family"; ?>, with a base size of <? echo "$font_size" ?>
pt.</p>
<P>Please feel free to <a href="session01.php">change your preferences</a> again.</p>
</BODY>
</HTML>
Unless you closed your Web browser between the last script and now, you should still be staring at the font family and font size selection form.
1. Select sans-serif for the font family.
2. Select 14 pt for the base font size.
3. Click on the Set Display Preferences button.
Displaying Changes
This is getting fun! With your Web browser still open to the confirmation screen for the initial preference changes, click on the Change Your Preferences link.
1. Select Courier for the font family.
2. Select 8 pt for the base font size.
3. Click on the Set Display Preferences button.