Articles: 843 | Categories: 148   
   
   
Home Articles Contact Us
 
 
 
 
Custom PHP Sessions (0 Comments)
Admin: Posted Date: March 3, 2010

PHP's session handling functions are OK, but what if you wanted to create your own sessions? In this article I will teach you how to create and maintain your own customized sessions.

Developing Custom PHP Sessions

Ever wondered how to make your own session handling functions with PHP. In this article Brian shows us how to do just that using PHP, MySQL and a bit of maths!If you were programming a user authorization system for your website, then you would use a session or a cookie to pass data. A session would store the data on the server and reference it by a unique key or ID. As your members browse through the member pages, his/her data could be displayed or used by fetching that data. Alternatively, you could use a cookie that stores the data on the users’ computer. Fetching the data from the cookie would be similar to a session except you use the cookie name: PHP handles the actual retrieval and sorting of the cookie data.

PHP's session handling functions are OK, but what if you wanted to create your own sessions? In this article I will teach you how to create and maintain your own customized sessions. You will have complete control over how your session handles the data and how it fetches the data to make it available in your scripts.

This is very useful because you can track users' IP addresses and other information you can grab with PHP. There are many more advantages to creating your own sessions as compared to using PHP's built-in session handing functions.

In this tutorial I will assume the following things:
  • You have PHP4+ ans MySql installed on your server.
  • You have strong PHP and MySQL skills.
  • You know object-oriented programming for PHP.
Anyhow, let's get started and work those customized PHP sessions!

Developing the Backend


First off, we need to plan out how we want to run our sessions by creating our table. You can add a separate database for the sessions, but I recommend setting up another table in your main database if you are using one. We'll start by making a new database assuming you want too. Run this set of code in your MySQL console application:

create database session;

create table sessions (
id int(10) NOT NULL AUTO_INCREMENT,
sess_key char(6) NOT NULL,
val varchar(250) NOT NULL,
ip varchar(35) NOT NULL,
access int(25) NOT NULL,
PRIMARY KEY(id)
);


We simply created a new database and table. The "sessions" table will hold all of our sessions that are actively running. As you become more familiar with how to make your own sessions, then you may want to tweak the table to optimize it for your needs.

Now let's take a look at where all of our code will reside and start learning how the sessions will work. We will need to create a new file, and let's name it sess.php. In that new file put the following code:

<?php

$host = "localhost";
$user = "user";
$pass = "pass";
$db = "db";

$dbc = mysql_connect($host,$user,$pass) or die("Cannot establish a connection to the database.");
mysql_select_db($db,$dbc);

class session {

var $key;
var $timeout;
}
?>


Be sure to change the database connection information to match the setup on your server. We have just defined the very basics of our sessions. We created a new class named session and defined two variables that will be our class methods. These two variables will hold the session key and timeout values.

Creating the Session Functions
I will begin by introducing our first class function. The function will be start() and it will initialize the session by generating the session key. It doesn't store anything in the database yet. You can set the timeout for the session when you call it, but it is optional.

// start() will initialize the session by generating the session key or ID
function start($timeout = "") {

// create an array with all the letters of the alphabet
$letters = range("a","z");
// declare the $key variable
$key = "";

// generate our session's key formatted such as #a#aa#
for($i = 0; $i < 6; $i++) {
if(($i == 0) || ($i == 2) || ($i == 5))
$key .= rand(0,9);
if(($i == 1) || ($i == 3) || ($i == 4))
$key .= $letters[rand(0,25)];
}

// store the session's key in a method of the class
$this->key = $key;

// perform a conditional to test if the user defined the timeout and if not store the default value.
if($timeout == "")
$this->timeout = 300; // five minutes
else
$this->timeout = $timeout;

return 0;
}



As you can see from the code above, we have created a new function called start(). The only argument, $timeout, is optional. If you don't set a value then the function will set the default value of 300 seconds (5 minutes) for timing out. If you define it, it must be in seconds for how long the session can be inactive.

Our function also generates a session key that is used to reference the session in the database. The key is based off the format #a#aa#. This function must be called right after you initialize the class in your login script or the script that will register the value to the session. It only needs to be called once.

Our next function is register() and it will take the argument $val and store it into the database. Let's take a look:

// this function will register a value to session. (only one value, see replace() to update the value)
function register($val) {

// if key is not generated run start()
if($this->key == "")
$this->start();

$insert = mysql_query("INSERT INTO sessions (sess_key, val, ip, sec_expire, stamp_expire, access) VALUES ('" . $this->key. "', '" . addslashes($val) . "' , '" . $_SERVER["REMOTE_ADDR"] . "' , " . $this->timeout . "," . (time() + $this->timeout) . "," . time() .");");
// set the cookie that will store the session key
setcookie("sess_key",$this->key,time()+3600);
}


At the start of the function you will see that we test to see if the key has been created or not. If you don't call start() before register() then it will run start(), but you don't get the option of setting the timeout. I've made our query bold so that it will be a little bit easier to read.

The session key, session value, users' IP, all the expiration details and last access information are stored. The access field contains the last time the user accessed the session before the session times out. This is important because the read() function, seen later on, will update that field and if it's not updated it will automatically time out after the specified timeout even if the user is active. Finally, we set a cookie that will contain our session key and will be used for future reference to the database.

Now let's take a look at our functions that read and expire the session. The first function is read(). It will read the session in the database, fetch it and store it to $sess_var. Here's the code:

function read() {

// set $sess_val global - the variable of the session value.
global $sess_val;

// if the cookie doesn't exisit send them back to the login screen.
if(!$_COOKIE["sess_key"]) {
header("Location: login.php");
exit;
}

// fetch the session key from the cookie.
$this->key = $_COOKIE["sess_key"];

// fetch the session value
$query = mysql_query("SELECT val FROM sessions WHERE sess_key = '" . $this->key . "'") or die("query failed - line 55");

if(mysql_num_rows($query) == 0) {
header("Location: login.php");
exit;
}

$fetch = mysql_fetch_array($query);

// store the session value to $sess_val
$sess_val = stripslashes($fetch["val"]);

// test if session has reached the expiration point
$this->expire();

// this code will only run if expire() returned falsed - we update the last access point to now.
$update = mysql_query("UPDATE sessions SET access = " . time() . " WHERE sess_key = '" . $this->key . "'") or die("query failed - line 70");

}


We tested the user in two places to see if they are logged in or not. The user is required to be logged in for the user to have the cookie and for the database entry to remain logged in. If not, they must login again.

Next, the code pulls the session value from the database and stores it in the $sess_val variable. When you are using the code in your pages to output the sessions' value, you should use the $sess_val variable. We will discuss that later on.

Finally, we test the session for expiration and if it returns false then it will update the last access field to "refresh" the session. I will now show you how to test the session for expiration. It's quite simple, but requires some mathematical skill.

// this function will test if the user has been inactive for the defined timeout
function expire() {

// fetch the last access and expirations from the database
$query = mysql_query("SELECT access, sec_expire, stamp_expire FROM sessions WHERE sess_key = '" . $this->key . "'") or die("query failed - line 78");
$fetch = mysql_fetch_array($query);

$access = $fetch["access"];
$expire = $fetch["sec_expire"];
$timeout = $fetch["stamp_expire"];

// test if session is expired based on defined timeout
if(($timeout - $access) <= ($expire - $expire)) {
$this->destory();
die("Your session has expired. Please re-login.");
}
}


All of our session timestamps and timeout values are stored in the database, so we fetch that information first. If $timeout (a regular timestamp plus the session timeout) minus the last time the session was accessed is less than or equal to the seconds for the session minus itself, then we destroy the session and inform the user. If false, the code continues to execute.

We now know our sessions pretty well. What if we wanted to change the value of the session because the value is the users' username? If the username is changed and the session isn’t updated and you test it, the script would think it's somebody else. No problem. Our next function is replace(). It simply updates the current value with a new value.



// this function will update the session value
function replace($val) {

// fetch the user key from cookie
$this->key = $_COOKIE["sess_key"];

// update the database with the new value
$query = mysql_query("UPDATE sessions SET val = '" . $val . "' WHERE sess_key = '" . $this->key) or die("query failed - line 77");
}


Our function asks for the new value and then it will update the current value with it. Finally, we reach our last function:

// this function will kill the session
function destroy($key = "") {

// fetch the user key from cookie
$this->key = $_COOKIE["sess_key"];

// delete session from database
$query = mysql_query("DELETE FROM sessions WHERE sess_key = '" . $this->key . "'") or die("query failed - line 86");

// remove cookie from the user's computer
$delete = setcookie("sess_key" , $this->key, time()-3600);

if($query && $delete) {
header("Location login.php");
exit;
}
}


The destroy() function will kill the session. It deletes the session from the database and removes the cookie from the users' computer. We now know everything about creating our sessions. We still have one more issue to cover, which is how to use them.

Using Our Sessions


(Page 4 of 5 )

Let's start by creating a new file named login php. Add the following code to login.php:

<?php

include "sess.php";

if($login) {

$sess = new session;

$sess->start();

$sess->register($username);

header("Location: welcome.php");

}

?>
<html>
<head>
<title>login</title>
</head>

<body>

<form method="post" action="<?= $PHP_SELF; ?>">

Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<br>
<input type="submit" name="login" value="Login">

</body>
</html>


The code above has our login form and if it's submitted it will initialize the class and use the proper functions to start and register the values. Then the user is redirected to the welcome.php page.



Last, but surly not least, we need to create our welcome.php page:

<?php

include "sess.php";

$sess = new session;

if($logout == "yes") {
$sess->destroy();
header(“Location: login.php”);
exit;
}

$sess->read();
?>
<html>
<head>
<title>welcome</title>
</head>

<body>

Welcome, <?= $sess_val; ?><br>
<a href="<?= $PHP_SELF; ?>?logout=yes">Logout</a>

</body>
</html>


Since this page is the first one to use our sessions with the passing key, we call the read() function to fetch the value. As seen in the read() function, we saved the value to $sess_val so where we want that data to appear we print it to the user. Then we offer a link to log out, which uses the destroy() function to kill the current session.

Using Our Sessions


Let's start by creating a new file named login php. Add the following code to login.php:

<?php

include "sess.php";

if($login) {

$sess = new session;

$sess->start();

$sess->register($username);

header("Location: welcome.php");

}

?>
<html>
<head>
<title>login</title>
</head>

<body>

<form method="post" action="<?= $PHP_SELF; ?>">

Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<br>
<input type="submit" name="login" value="Login">

</body>
</html>


The code above has our login form and if it's submitted it will initialize the class and use the proper functions to start and register the values. Then the user is redirected to the welcome.php page.

Last, but surly not least, we need to create our welcome.php page:

<?php

include "sess.php";

$sess = new session;

if($logout == "yes") {
$sess->destroy();
header(“Location: login.php”);
exit;
}

$sess->read();
?>
<html>
<head>
<title>welcome</title>
</head>

<body>

Welcome, <?= $sess_val; ?><br>
<a href="<?= $PHP_SELF; ?>?logout=yes">Logout</a>

</body>
</html>


Since this page is the first one to use our sessions with the passing key, we call the read() function to fetch the value. As seen in the read() function, we saved the value to $sess_val so where we want that data to appear we print it to the user. Then we offer a link to log out, which uses the destroy() function to kill the current session.

Conclusion

You may have noticed that our sessions can be improved upon greatly. I've shown you one of the easiest ways of creating and maintaining your own sessions. If you are planning to improve the code seen in this article, then here are some ideas for expansion:
  • Instead of using a cookie to pass the key you can configure Apache to pass with folders. For example, www.domain.com/members/5i1hk6/welcome.php.
  • What if the user closed his/her browser before logging out? You may want to set up a cron job to run every five minutes to remove inactive sessions to keep the database clean.
  • You could also build an administration area to quickly configure your sessions and see who’s online and possibly kick them off whenever you desire.

 

 

 
 
Add a Comment:
 
(You must be signed in to comment on an article. Not a member? Click here to register)
   
Title:

Comments: