<

Use sessions to register and track users

Published on
7,962 Points
1,862 Views
1 Endorsement
Last Modified:
Approved
Chris Gralike
Not too political, always looking for the best advice or solution, and if need be using a pragmatic approach.
In effect this is a session handler that registers sessions inside a database and verifies them based on a timestamp (session timeout). This code is just an skeleton that needs to be extended and altered to your own needs.

Installing is done in two steps.
First, create this table inside your mysql server.

Next create a new PHP file including the attached code snippet.
 
<?php 
class Sessions{
	private $id;			#Will contain the session ID generated from the inser ID in the database
	private $CTS;			#Holds the "Current Timeout"
	private $dbname;		#Database name that contains the session table
	private $dbhost;		#Database host that contains the deatabase containing the session table
	private $dbuser;		#Database user used to connect to the database.
	private $dbpass;		#Database Password used to connect to the database, assuming that one is always used.
	private $dblink;		#Strict var used to hold the link identifier created on database connect.
	private $timeout; 
	public function __construct($dbuser, $dbpass, $dbhost, $dbname, $session_timeout=''){
		if(!empty($dbuser) && !empty($dbpass) && !empty($dbhost) && !empty($dbname)){
			$this->dbuser = $dbuser;
			$this->dbpass = $dbpass; #assuming we always use a password
			$this->dbhost = $dbhost;
			$this->dbname = $dbname;
		}
		
		// Define a timeout.
		$this->timeout = (!empty($session_timeout)) ? $session_timeout : "5";
		
		// Start our session //
		session_start();
		
		// We redirect on error, so this is to prevent a redirect loop... //
		if(!isset($_SESSION['failcount'])){
			$_SESSION['failcount'] = 0;
		}
		
		// this is our error handler :P !//
		if(isset($_SESSION['failcount'])){
			if($_SESSION['failcount'] > 10){
				$err = '';
				if(@is_array($_SESSION['errors'])){
					foreach($_SESSION['errors'] as $key => $value){
						$err .= "$key => $value<br/>";
					}
				}else{
					$err = 'unknown error!';
				}
				die('Failed 10x to setup a decent session<br/>The following errors where reported!<br/>'.$err);
			}
		}
		
		// Create the current timestamp to work with // 
		$this->CTS = ((date('d')*3600)+(date('g') * 60)+date('i'));
		
		// Create a db connection to test connectivity//
		if(!$this->dbConnect()){ 
			$_SESSION['errors']['dbconnect'] = 'failed to connect to DB';
			// Unset the session active var //
			unset($_SESSION['active']);
			// Register the fact this happend // 
			$_SESSION['failcount']++;
			header('location:'.$_SESSION['location']);
		}
		
		// Cleanup old sessions (timed out sessions) //
		$this->CleanDb();
		
		// Validate this session //
		if(!isset($_SESSION['active'])){
			if($this->RegisterSession()){
				$this->dbClose();
				return true;
			}else{
				$this->dbClose();
				return false;
			}
		}else{
			$this->VerifySession();
			$this->dbClose();
		}
	}
    
	public function getOnline(){
		$this->dbConnect();
		if(is_resource($this->dblink)){
			$sql = 'SELECT DISTINCT COUNT(*) as online FROM session';
			$result = mysql_query($sql);
			$row = mysql_fetch_array($result);
			$this->dbClose();
			if($row['online'] > 0){
				return $row['online'];
			}else{
				return 1;
			}
		}else{
			return false;
		}
	}
	
	// Get number of minutes online
	public function getBrowseTime(){
		return $_SESSION['ttime'];
	}
	
	public function getStartTime(){
		$secs = $_SESSION['btime'] * 60;
		$hours = round(($secs  / (60 * 60) %24));
		$min = round(($secs  / 60) %60);
		return $hours .":". $min;
	}
	
	public function whoami(){
		return $_SESSION['username'];
	}
	
	// Open a database connection.
	private function dbConnect(){
		if(!empty($this->dbuser) && !empty($this->dbpass) && !empty($this->dbhost)){
			if(@$this->dblink = mysql_connect($this->dbhost, $this->dbuser, $this->dbpass)){
				if(@mysql_select_db($this->dbname, $this->dblink)){
					return $this->dblink;
				}else{
					$_SESSION['errors']['database'] = 'no valid database could be selected';
				}
			}else{
				$_SESSION['errors']['database'] = 'Connection with database failed';
			}
		}else{
			$_SESSION['errors']['database'] = 'Not all required db connection info was available';
		}
		return false;
	}
	
	private function dbClose(){
		if(is_resource($this->dblink)){
			mysql_close($this->dblink);
		}
	}
	
	// Clean up all timed out session registrations.
	private function CleanDb(){
		if(is_resource($this->dblink)){
			$sql = 'select * from session';
			$result = mysql_query($sql, $this->dblink);
			while($row = mysql_fetch_array($result)){
				$tdiff = $this->CTS - $row['sess_ltime'];
				if($tdiff >= $this->timeout){
					$delete = 'DELETE FROM session where sess_id = "'.$row['sess_id'].'"';
					mysql_query($delete);
				}
			}
		}else{
			$_SESSION['errors']['dbclean'] = 'No db link resource for cleanup';
		}
	
	}
	// Method to handle registrations // 
	private function RegisterSession(){
		// Hold all the session information available inside the _Session var.
		$_SESSION['active']    = true;
		$_SESSION['name']      = session_name();
		$_SESSION['btime']     = $this->CTS;
		$_SESSION['ltime']     = $this->CTS;
		$_SESSION['ttime']     = '1';
		$_SESSION['username']  = 'guest';
		$_SESSION['location']  = $_SERVER['REQUEST_URI'];
		
		if(is_resource($this->dblink)){
			$sql = 'INSERT INTO session(sess_name, sess_btime, sess_ltime, sess_ttime, sess_username, sess_location)
			        VALUES("'.$_SESSION['name'].'","'.$_SESSION['btime'].'","'.$_SESSION['ltime'].'",
					       "'.$_SESSION['ttime'].'","'.$_SESSION['username'].'","'.$_SESSION['location'].'")';
			if(mysql_query($sql, $this->dblink)){
				$_SESSION['id'] = mysql_insert_id();
				// If we had any failures we reset them here //
				$_SESSION['failcount'] = 0;
				return true;
			}else{
				$_SESSION['errors']['register'] = 'failed to register session inside the database, online info might not be available';
				// Unset the session active var //
				unset($_SESSION['active']);
				// Register the fact this happend // 
				$_SESSION['failcount']++;
				header('location:'.$_SESSION['location']);
			}
		}else{
			$_SESSION['errors']['register'] = 'unable to register session, no database link available';
			// Unset the session active var //
			unset($_SESSION['active']);
			// Register the fact this happend // 
			$_SESSION['failcount']++;
			header('location:'.$_SESSION['location']);
		}
	
	}
	
	private function VerifySession(){
		if(isset($_SESSION['active'])){
			if(is_resource($this->dblink)){
				$sql = 'SELECT * from session where sess_id = "'.$_SESSION['id'].'"';
				if($result = mysql_query($sql)){
					$row = mysql_fetch_array($result);
					if(isset($row['sess_id'])){
						//Verify the times again for a timeout //
						$tdiff = $this->CTS - $row['sess_ltime'];
						if($tdiff >= $this->timeout){
							// If the session timedout//
							// Delete the session from the database //
							$delete = 'DELETE FROM session where sess_id = "'.$row['sess_id'].'"';
							mysql_query($delete);
							// Unset the session active var //
							unset($_SESSION['active']);
							// Register the fact this happend // 
							$_SESSION['failcount']++;
							header('location:'.$_SESSION['location']);
						}else{
							// Hold all the session information available inside the _Session var.
							$_SESSION['ttime'] = $this->CTS - $row['sess_btime'];
							$_SESSION['ltime'] = $this->CTS;
							$_SESSION['location']  = $_SERVER['REQUEST_URI'];	
							// We need to update the fact we had activity ;-) //
							
							$update = 'UPDATE session SET sess_ltime="'.$this->CTS.'", sess_ttime="'.$_SESSION['ttime'].'", sess_location="'.$_SESSION['location'].'"
							           WHERE sess_id = "'.$_SESSION['id'].'"';
							mysql_query($update);
							return true;
						}
					}else{
						// Session was allready delete from database. Other users browsing maybe? :)
						// Handle it like a timedout session.
						unset($_SESSION['active']);
						// Register the fact this happend.
						$_SESSION['failcount']++;
						header('location:'.$_SESSION['location']);
					}
				}else{
					// The query failed for unkown reasons//
					unset($_SESSION['active']);
					// Register the fact this happend. 
					$_SESSION['failcount']++;
					header('location:'.$_SESSION['location']);
				}
			
			}else{
				$_SESSION['errors']['verify'] = 'No dblink available for verification';
				unset($_SESSION['active']);
				return false;
			}
		}else{
			die('H4(k 4t73mpt!');
		}
	}
}

Open in new window


For example you created a file called "session.class.php" that contains the code, you then need to upload that file to your webserver.

Next you need to guarantee that this file is loaded and initialized each time a user browses to a new location, usually this is done by including this file and initialization code to the header of your page(s).

Including the file works like this;
 
<?php
$PHPEx='.php';
include('session.class'.$PHPEx);
?>

Open in new window


When this is done you need to initialize the class after which you are able to access it using the following directives;
 
<?php
$session = new Sessions('dbuser', 'dbpass', 'dbhost', 'dbname', 'timeout in min');
echo "There are:".$session->getOnline()." users online.<br />";
echo "You started browsing at :".$session->getStartTime()."u<br />";
echo "Our current time is ".date('h:i')."u <br />";
echo "You have been active for :".$session->getBrowseTime()."Mins.<br />";
echo "You are known as :".$session->whoami()."<br />";
?>

Open in new window


You can also add all the snippets inside one file and include that in your application.

Again, this class still needs allot of work if you want it to maintain "loggedin" users and related sessions. In this stage the "how many users are online" can be queried and own session information like how long have iv been browsing.

Good luck on extending this class.

Rgrds, Chris
1
Comment
1 Comment
 
LVL 11

Author Comment

by:Chris Gralike
If you get this error :

Failed 10x to setup a decent session
The following errors where reported!
database => Connection with database failed
dbconnect => failed to connect to DB
dbclean => No db link resource for cleanup
register => unable to register session, no database link available

Then check your database connection information. For the everyone that dont read code comments, this class "ONLY" accepts database login "USING PASSWORD". The blanks are not accounted for in the code.

Good luck and rgrds,
0

Featured Post

Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

Join & Write a Comment

Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month