Index
    Preface
      What This Book Is About
      What You Need to Know
      How This Book Is Organized
      How to Use This Book
      Conventions Used in This Book
      Using Code Examples
      How to Contact Us
      Web Site and Code Examples
      Acknowledgments
      Chapter 1.  Database Applications and the Web
      Section 1.1.  The Web
      Section 1.2.  Three-Tier Architectures
      Chapter 2.  The PHP Scripting Language
      Section 2.1.  Introducing PHP
      Section 2.2.  Conditions and Branches
      Section 2.3.  Loops
      Section 2.4.  Functions
      Section 2.5.  Working with Types
      Section 2.6.  User-Defined Functions
      Section 2.7.  A Working Example
      Chapter 3.  Arrays, Strings, and Advanced Data Manipulation in PHP
      Section 3.1.  Arrays
      Section 3.2.  Strings
      Section 3.3.  Regular Expressions
      Section 3.4.  Dates and Times
      Section 3.5.  Integers and Floats
      Chapter 4.  Introduction to Object-Oriented Programming with PHP 5
      Section 4.1.  Classes and Objects
      Section 4.2.  Inheritance
      Section 4.3.  Throwing and Catching Exceptions
      Chapter 5.  SQL and MySQL
      Section 5.1.  Database Basics
      Section 5.2.  MySQL Command Interpreter
      Section 5.3.  Managing Databases and Tables
      Section 5.4.  Inserting, Updating, and Deleting Data
      Section 5.5.  Querying with SQL SELECT
      Section 5.6.  Join Queries
      Section 5.7.  Case Study: Adding a New Wine
      Chapter 6.  Querying Web Databases
      Section 6.1.  Querying a MySQL Database Using PHP
      Section 6.2.  Processing User Input
      Section 6.3.  MySQL Function Reference
      Chapter 7.  PEAR
      Section 7.1.  Overview
      Section 7.2.  Core Components
      Section 7.3.  Packages
      Chapter 8.  Writing to Web Databases
      Section 8.1.  Database Inserts, Updates, and Deletes
      Section 8.2.  Issues in Writing Data to Databases
      Chapter 9.  Validation with PHP and JavaScript
      Section 9.1.  Validation and Error Reporting Principles
      Section 9.2.  Server-Side Validation with PHP
      Section 9.3.  JavaScript and Client-Side Validation
      Chapter 10.  Sessions
      Section 10.1.  Introducing Session Management
      Section 10.2.  PHP Session Management
      Section 10.3.  Case Study: Using Sessions in Validation
      Section 10.4.  When to Use Sessions
      Section 10.5.  PHP Session API and Configuration
      Chapter 11.  Authentication and Security
      Section 11.1.  HTTP Authentication
      Section 11.2.  HTTP Authentication with PHP
      Section 11.3.  Form-Based Authentication
      Section 11.4.  Protecting Data on the Web
      Chapter 12.  Errors, Debugging, and Deployment
      Section 12.1.  Errors
      Section 12.2.  Common Programming Errors
      Section 12.3.  Custom Error Handlers
      Chapter 13.  Reporting
      Section 13.1.  Creating a Report
      Section 13.2.  Producing PDF
      Section 13.3.  PDF-PHP Reference
      Chapter 14.  Advanced Features of Object-Oriented Programming in PHP 5
      Section 14.1.  Working with Class Hierarchies
      Section 14.2.  Class Type Hints
      Section 14.3.  Abstract Classes and Interfaces
      Section 14.4.  Freight Calculator Example
      Chapter 15.  Advanced SQL
      Section 15.1.  Exploring with SHOW
      Section 15.2.  Advanced Querying
      Section 15.3.  Manipulating Data and Databases
      Section 15.4.  Functions
      Section 15.5.  Automating Querying
      Section 15.6.  Table Types
      Section 15.7.  Backup and Recovery
      Section 15.8.  Managing Users and Privileges
      Section 15.9.  Tuning MySQL
      Chapter 16.  Hugh and Dave's Online Wines:A Case Study
      Section 16.1.  Functional and System Requirements
      Section 16.2.  Application Overview
      Section 16.3.  Common Components
      Chapter 17.  Managing Customers
      Section 17.1.  Code Overview
      Section 17.2.  Customer Validation
      Section 17.3.  The Customer Form
      Chapter 18.  The Shopping Cart
      Section 18.1.  Code Overview
      Section 18.2.  The Winestore Home Page
      Section 18.3.  The Shopping Cart Implementation
      Chapter 19.  Ordering and Shipping at the Online Winestore
      Section 19.1.  Code Overview
      Section 19.2.  Credit Card and Shipping Instructions
      Section 19.3.  Finalizing Orders
      Section 19.4.  HTML and Email Receipts
      Chapter 20.  Searching and Authentication in the Online Winestore
      Section 20.1.  Code Overview
      Section 20.2.  Searching and Browsing
      Section 20.3.  Authentication
      Appendix A.  Linux Installation Guide
      Section A.1.  Finding Out What's Installed
      Section A.2.  Installation Overview
      Section A.3.  Installing MySQL
      Section A.4.  Installing Apache
      Section A.5.  Installing PHP
      Section A.6.  What's Needed for This Book
      Appendix B.  Microsoft Windows Installation Guide
      Section B.1.  Installation Overview
      Section B.2.  Installing with EasyPHP
      Section B.3.  What's Needed for This Book
      Appendix C.  Mac OS X Installation Guide
      Section C.1.  Getting Started
      Section C.2.  Installing MySQL
      Section C.3.  Setting Up Apache and PHP
      Section C.4.  What's Needed for This Book
      Appendix D.  Web Protocols
      Section D.1.  Network Basics
      Section D.2.  Hypertext Transfer Protocol
      Appendix E.  Modeling and Designing Relational Databases
      Section E.1.  The Relational Model
      Section E.2.  Entity-Relationship Modeling
      Appendix F.  Managing Sessions in theDatabase Tier
      Section F.1.  Using a Database to Keep State
      Section F.2.  PHP Session Management
      Section F.3.  MySQL Session Store
      Appendix G.  Resources
      Section G.1.  Client Tier Resources
      Section G.2.  Middle-Tier Resources
      Section G.3.  Database Tier Resources
      Section G.4.  Security and Cryptography Resources
      Appendix H.  The Improved MySQL Library
      Section H.1.  New Features
      Section H.2.  Getting Started
      Section H.3.  Using the New Features
    Colophon
    Copyright



 

Previous Section  < Day Day Up >  Next Section

F.3 MySQL Session Store

In this section we develop a set of user-defined handlers that store session variables in a MySQL table.

F.3.1 Session Table Structure

For the session handler code that stores session variables, a table is needed to hold sessions. You can create the table as part of your application database (for example, as a table in the winestore database), or create a new database to store only sessions. We follow the former approach, but it doesn't matter what you choose in practice; the database is accessed using its own connection, so you won't have any trouble accessing the table even when other tables are locked.

The following SQL CREATE TABLE statement creates a table to hold the session ID, the serialized session variables, and a timestamp to indicate when the session was last accessed. If you want to add it to the winestore database, login to the MySQL command interpreter as root user and type the following:

mysql> use winestore;

Database changed

mysql> CREATE TABLE PHPSESSION(

    ->   session_id varchar(50) NOT NULL,

    ->   session_variable text,

    ->   last_accessed decimal(15,3) NOT NULL,

    ->   PRIMARY KEY (session_id),

    ->   KEY last_acc (last_accessed)

    -> ) type=MyISAM;

Query OK, 0 rows affected (0.05 sec)

The session_id attribute is the primary key and the last_accessed attribute is indexed to allow fast deletion of dormant sessions using custom garbage-collection code described later.

When the code is up and running, the PHPSESSION table can be examined to see the current sessions. The following example shows that two sessions are held in the table (we have truncated the values in the session_id column to fit on the page):

mysql> SELECT * FROM PHPSESSION;

+---------------------+------------------------------+--------------+

| session_id          | session_variable             | last_updated |

+---------------------+------------------------------+--------------+

| ee83912e13b11a8c042 | count|i:39;start|i:90900585; | 90900661.575 |

| 6e721f8557df77b7b6d | count|i:0;start|i:90900677;  | 90900678.705 |

+---------------------+------------------------------+--------------+

2 rows in set (0.02 sec)

F.3.2 Handler Implementations

We store the session handlers in a support file. By placing the functions shown in Examples Example F-1 through Example F-8 in the one file, you can require that file at the beginning of any PHP script that uses sessions. If the file is saved as mysql_sessions.inc, then it's required as shown in the following example:

<?php

  require "mysql_sessions.inc";

  start_session( );



  //... rest of the script ...

?>

F.3.2.1 Support functions

The MySQL-based session handlers can use the simple showerror( ) function discussed in Chapter 6 or the custom error handler developed in Chapter 12. To keep the examples simple, we use the showerror( ) function that's stored in the db.inc require file. Using this approach, when an error occurs, the function reports a MySQL error message and stops the script. If you use a custom handler instead and replace the calls to showerror( ) with calls to trigger_error( ) , then you can handle errors more gracefully by logging them to a file and presenting an error message to the user that has a look and feel that's consistent with the application.

The db.inc file that contains showerror( ) also maintains the database credentials, stored in the $hostName, $username, and $password variables.

Example F-1 shows the function getMicroTime( ) , which generates a timestamp. The timestamp records the last session access by the sessionWrite( ) handler and creates a query that identifies idle sessions in the sessionGC( ) handler. The sessionWrite( ) handler and the sessionGC( ) handler are developed later in this section.

Example F-1. The support function getMicroTime( )
<?php

require "db.inc";



// Returns current time as a number. Used for recording the

// last session access.



function getMicroTime( )

{

  // microtime( ) returns the number of seconds since

  // 0:00:00 January 1, 1970 GMT as a  microsecond part

  // and a second part. e.g.: 0.08344800 1000952237



  // Convert the two parts into an array

  $mtime = explode(" ", microtime( ));



  // Return the addition of the two parts e.g.: 1000952237.08344800

  return($mtime[1] + $mtime[0]);

}

F.3.2.2 Session open handler

Example F-2 shows the first of the session handlers required by PHP session management. When PHP calls the sessionOpen( ) function, the values of session.save_path and session.name defined in the php.ini file, are passed as parameters and these values can be used however you choose. In the sessionOpen( ) function defined here, these two parameters identify the database and table used to store session variables.

The $database_name parameter—the value of session.save_path—is used to select a database after a connection to a MySQL server is established. The $table_name parameter—the value of session.name—is stored in the global variable $session_table. The global variables $session_table and $connection appear in subsequent session store handlers, where they are used to execute SELECT, INSERT, UPDATE, and DELETE queries.

Example F-2. The sessionOpen( ) handler
// The database connection

$connection = NULL;

  

// The global variable that holds the table name

$session_table = NULL;



// The session open handler called by PHP whenever

// a session is initialized. Always returns true.



function sessionOpen($database_name, $table_name)

{

  // Save the database connection in a global variable

  global $connection;



  // Save the session table name in a global variable

  global $session_table;



  // Database credentials

  global $hostName;

  global $username;

  global $password;



  if (!($connection = @ mysql_connect($hostName, $username, $password)))

     showerror( );



  if (!mysql_select_db($database_name, $connection))

     showerror( );



  $session_table = $table_name;



  return true;

}

With the handler shown in Example F-2, the database and table names can be configured in the php.ini file. For example, with the following php.ini file settings:

session.save_path = winestore

session.name = PHPSESSION

the openSession( ) function selects the winestore database and identifies the PHPSESSION table. If you want to use our session handler, you need to modify your php.ini to have these settings and restart your Apache.

F.3.2.3 Session read handler

The sessionRead( ) handler function shown in Example F-3 is called by PHP to read session variables. The handler returns the serialized string that holds the session variables for the session ID $sess_id. The function executes a query to find the row with a session_id equal to $sess_id and, if the row is found, the session_variable attribute is returned. If no session is found, sessionRead( ) returns a blank string.

The sessionRead( ) handler uses the global variables $session_table and $connection, set up by the sessionOpen( ) handler, to formulate and execute the query. The function returns all the session variables as a serialized string and PHP's session management layer automatically deserializes the string to set up the $_SESSION array; you don't have to worry about serialization and deserialization in your code.

Example F-3. The sessionRead( ) handler
// This function is called whenever a session_start( ) call is

// made and reads the session variables associated with the session

// identified by the $sess_id parameter. Returns "" when a session

// is not found and the session variables as a serialized string

// when the session exists.



function sessionRead($sess_id)

{

  // Access the DBMS connection

  global $connection;



  // Access the sessions table

  global $session_table;



  // Formulate a query to find the session identified by $sess_id

  $search_query = "SELECT * FROM {$session_table}

                   WHERE session_id = '{$sess_id}'";



  // Execute the query

  if (!($result = @ mysql_query($search_query, $connection)))

     showerror( );



  if(mysql_num_rows($result) == 0)

    // No session found - return an empty string

    return "";

  else

  {

    // Found a session - return the serialized string

    $row = mysql_fetch_array($result);

    return $row["session_variable"];

  }

}

F.3.2.4 Session write handler

The sessionWrite( ) handler function is called by PHP at the end of a script that calls session_start( ), and is responsible for writing variables to the session store and for recording when a session was last accessed. It's important that the last_access time-stamp is updated each time the sessionWrite( ) handler is called, even if the session variables haven't changed. If the last access time isn't updated, a session may be seen as dormant by the garbage collection handler and destroyed even though the variables have recently been read.

Example F-4 starts by executing a SELECT query to determine if a session exists. If a session is found, an UPDATE query is executed; otherwise a new session row is created with an INSERT query. Both the INSERT and UPDATE queries set the last_accessed field with the timestamp created by the support function getMicroTime( ) shown in Example F-1.

Example F-4. The sessionWrite( ) handler
function sessionWrite($sess_id, $val)

{

  // Access the DBMS connection

  global $connection;



  // Access the sessions table

  global $session_table;



  $time_stamp = getMicroTime( );



  $search_query = "SELECT session_id FROM {$session_table}

                   WHERE session_id = '{$sess_id}'";



  // Execute the query

  if (!($result = @ mysql_query($search_query, $connection)))

     showerror( );



  if(mysql_num_rows($result) == 0)

  {

     // No session found, insert a new one

     $insert_query = "INSERT INTO {$session_table}

                      (session_id, session_variable, last_accessed)

                      VALUES ('{$sess_id}', '{$val}', {$time_stamp})";



     if (!mysql_query($insert_query, $connection))

        showerror( );

  }

  else

  {

     // Existing session found - Update the session variables

     $update_query = "UPDATE {$session_table}

                      SET session_variable = '{$val}',

                          last_accessed = {$time_stamp}

                      WHERE session_id = '{$sess_id}'";



     if (!mysql_query($update_query, $connection))

        showerror( );

  }

}

F.3.2.5 Session close handler

The sessionClose( ) handler is called by PHP when a session-based script ends, and can be used to perform any housekeeping functions needed to close a session store. The handler implementation shown in Example F-5, accomplishes the minimum, just returning true.

Example F-5. The sessionClose( ) handler
// This function is executed on shutdown of the session. 

// Always returns true.



function sessionClose( )

{

    return true;

}

F.3.2.6 Session destroy handler

When session_destroy( ) is called, PHP calls the sessionDestroy( ) handler shown in Example F-6. This function deletes the row identified by the $sess_id argument from the table that holds the session variables.

Example F-6. The sessionDestroy( ) handler
// This is called whenever the session_destroy( ) function

// call is made. Returns true if the session  has successfully

// been deleted.



function sessionDestroy($sess_id)

{

  // Access the DBMS connection

  global $connection;



  // Access the sessions table

  global $session_table;



  $delete_query = "DELETE FROM {$session_table}

                   WHERE session_id = '{$sess_id}'";



  if (!($result = @ mysql_query($delete_query, $connection)))

     showerror( );



  return true;

}

F.3.2.7 Garbage collection handler

The last handler to be defined is the garbage collection function. Example F-7 shows the implementation of sessionGC( ) , which queries for all session rows that have been dormant for $max_lifetime seconds. When PHP session management calls this function, the value of the session.gc_maxlifetime parameter is passed as $max_lifetime. The time a session has been dormant is calculated by subtracting the last update time held in the session row from the current time.

Example F-7. The sessionGC( ) garbage collection handler
// This function is called on a session's start up with the

// probability specified in session.gc_probability.  Performs

// garbage collection by removing all sessions that haven't been

// updated in the last $max_lifetime seconds as set in

// session.gc_maxlifetime.

// Returns true if the DELETE query succeeded.



function sessionGC($max_lifetime)

{

  // Access the DBMS connection

  global $connection;



  // Access the sessions table

  global $session_table;



  $current_time = getMicroTime( );



  $delete_query = "DELETE FROM {$session_table}

             WHERE last_accessed < ({$current_time} - {$max_lifetime})";



  if (!($result = @ mysql_query($delete_query, $connection)))

     showerror( );



  return true;

}

F.3.2.8 Registering session handlers

Finally, the handlers implemented in Examples Example F-2 through Example Example F-7 need to be registered as callback functions with PHP. Example F-8 shows the call to session_set_save_handler( ) with the names of each handler function.

Example F-8. Registering the user-defined session handlers with PHP
// Call to register user call back functions.



session_set_save_handler("sessionOpen", 

                         "sessionClose", 

                         "sessionRead", 

                         "sessionWrite", 

                         "sessionDestroy", 

                         "sessionGC");

?>

F.3.3 Using the User-Defined Session Handler Code

Once the user-defined session handler code is implemented, it can be used by setting up the session configuration in the php.ini file and including the library at the top of PHP scripts that use sessions. The session.save_handler parameter needs to be set to user, indicating that user-defined handlers are used; the session.save_path parameter is set to the name of the database; and, session.name parameter is set to the name of the table. The following example settings are used if session variables are stored in the PHPSESSION table of the winestore database:

session.save_handler = user

session.save_path = winestore

session.name = PHPSESSION

After changing php.ini, you need to restart Apache for the settings to take effect.

Example F-9 shows how application scripts are modified to use the MySQL session store; the script is a copy of Example 10-1, with the addition of the directive to require mysql_session.inc.

Example F-9. A simple PHP script that uses the MySQL session store
<?php

  require_once "HTML/Template/ITX.php";

  require "mysql_sessions.inc";



  // This call either creates a new session or finds an existing one.

  session_start( );



  // Check if the value for "count" exists in the session store

  // If not, set a value for "count" and "start"

  if (!isset($_SESSION["count"]))

  {

    $_SESSION["count"] = 0;

    $_SESSION["start"] = time( );

  }



  // Increment the count

  $_SESSION["count"]++;



  $template = new HTML_Template_ITX("./templates");

  $template->loadTemplatefile("example.d-10.tpl", true, true);



  $template->setVariable("SESSION", session_id( ));

  $template->setVariable("COUNT", $_SESSION["count"]);

  $template->setVariable("START", $_SESSION["start"]);

  $duration = time( ) - $_SESSION["start"];

  $template->setVariable("DURATION", $duration);



  $template->parseCurrentBlock( );



  $template->show( );

?>

The script uses the template shown in Example F-10.

Example F-10. The template used with Example F-9
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

                      "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>Session State Test</title>

</head>

<body>

    <p>This page points at a session {SESSION}

    <br>count = {COUNT}

    <br>start = {START}

    <p>This session has lasted {DURATION} seconds.

</body>

</html>

F.3.4 PEAR's HTTP_Session Package

The PEAR HTTP_Session module is another example of PHP session handlers that implement a MySQL based session store. We introduce PEAR in Chapter 10.

The module has been developed to define an HTTP_Session class that provides a higher-level API to the PHP session management than the code we've developed here. The HTTP_Session class includes functions that not only access session variables, but also provide control over the session parameters such as cookies. HTTP_Session includes a database container method HTTP_Session::setContainer( ) that sets up PHP to use MySQL session handlers.

    Previous Section  < Day Day Up >  Next Section







    Copyright © 2010 | Domen maybe sale - bye this domen