Display the number of visitors to your website

In today’s Code for Fun section I’ll show you a simple way of displaying the number of online visitors to your site.

The code implements the Template method Pattern and the number of online visitors is saved into a file of your choice.

As you saw in the Template method Pattern article the class structure is very simple and straightforward:

//@ BASE CLASS
abstract class AbstractUsersOnline
{
	//@ Define methods that MUST be implemented
	//@ in all derived classes
	abstract protected function AddUser();
	abstract protected function CheckUsers();
	abstract protected function CountUsers();
 
	//@ Retrieve the IP address
	protected function GetIP() { /*{ TO DO }*/ }
	/**
	* ## The Template Method
	*
	* Retrieve the number of online users.
	* @return int
	*/
	public function CountOnlineUsers()
	{
		$this->CheckUsers();
		$this->AddUser();
		return $this->CountUsers();
	}
}
 
//@ DERIVED CLASS
class File_UsersOnline extends AbstractUsersOnline
{
	//@ IMPLEMENT ABSTRACT METHODS
	protected function AddUser() { /*{ TO DO }*/ }
	protected function CheckUsers() { /*{ TO DO }*/ }
	protected function CountUsers() { /*{ TO DO }*/ }
}

All we have to do now is to implement the defined steps:

/**
* abstract class UsersOnline
* Defines the course of action
*/
abstract class AbstractUsersOnline
{
	// Methods that MUST be implemented
	// in all derived classes
	abstract protected function AddUser();
	abstract protected function CheckUsers();
	abstract protected function CountUsers();
 
	/**
	* @internal
	* Retrieve the IP address of the visitors.
	* @return string
	*/
	protected function GetIP()
	{
		$HCIP	= isset($_SERVER['HTTP_CLIENT_IP']) 	  ? $_SERVER['HTTP_CLIENT_IP'] 		 : '0.0.0.0';
		$HXF 	= isset($_SERVER['HTTP_X_FORWARDED']) 	  ? $_SERVER['HTTP_X_FORWARDED'] 	 : '0.0.0.0';
		$HXFF 	= isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : '0.0.0.0';
		$RMAD 	= isset($_SERVER['REMOTE_ADDR']) 		  ? $_SERVER['REMOTE_ADDR'] 		 : '0.0.0.0';
 
		$ipAddress = ($HCIP) ? $HCIP : ($HXF) ? $HXF : ($HXFF) ? $HXFF : ($RMAD) ? $RMAD : '0.0.0.0';
		return $ipAddress;
	}
 
	/**
	* ## Template method
	*
	* Retrieve the number of online users.
	* @return int
	*/
	public function CountOnlineUsers()
	{
		$this->CheckUsers();
		$this->AddUser();
		return $this->CountUsers();
	}
 
}
// >> END CLASS AbstractUsersOnline
 
 
/**
* class File_UsersOnline
*
* Retrieve the number of online users. Data is saved into a file
*/
class File_UsersOnline extends AbstractUsersOnline
{
	/**
	* In minutes, the amount of time a user's session is considered active
	* @type int
	*/
	private $timeout = 5;
 
	/**
	* The full path to the file where the users will be stored
	* @type string
	*/
	private $filePath = '';
 
 
	/**
	* Constructor
	* @triggers E_USER_NOTICE
	*/
	public function __construct( $filePath, $timeout = 5 )
	{
		if ( ! is_file($filePath))
		{
			trigger_error('The file: '.$filePath.' was not found nor it could be created!', E_USER_NOTICE);
		}
		if ( ! is_readable($filePath))
		{
			trigger_error('The file: '.$filePath.' cannot be read!', E_USER_NOTICE);
		}
		if ( ! is_writable($filePath))
		{
			trigger_error('The file: '.$filePath.' needs writing permissions(0755 or 0777)!', E_USER_NOTICE);
		}
 
		$this->timestamp = time();
 
		if (intval($timeout) < 1) { $timeout = 5; }
 
		$timeout *= 60; // transform in seconds
		$this->timeout = $timeout;
		$this->filePath = $filePath;
	}
 
	/**
	* Add a new user to the list.
	* @return boolean
	*/
	protected function AddUser()
	{
		$data = array(
			 'timestamp' => $this->timestamp
			,'ip_address' => $this->GetIP()
		);
 
		$content = file_get_contents($this->filePath);
 
		if (empty($content))
		{
			$a = array();
			array_push($a, $data);
			file_put_contents($this->filePath, serialize($a), LOCK_EX);
		}
		else
		{
			$temp = unserialize($content);
			// prevent duplicate entries
			foreach( $temp as $entry)
			{
				if ($data['ip_address'] == $entry['ip_address'])
				{
					// IP exists. return.
					return false;
				}
			}
			array_push($temp,$data);
			file_put_contents($this->filePath, serialize($temp), LOCK_EX);
		}
		return true;
	}
 
	/**
	* Check to see if a user's session has expired and remove it from the list.
	* @return void
	*/
	protected function CheckUsers()
	{
		if (file_exists($this->filePath))
		{
			$content = file_get_contents($this->filePath);
 
			if ( ! empty($content))
			{
				$data = unserialize($content);
				$numData = count($data);
				for ($i=0; $i < $numData; $i++)
				{
					if (isset($data[$i]['timestamp']))
					{
						if ($data[$i]['timestamp'] < ($this->timestamp - $this->timeout))
							unset($data[$i]);
					}
				}
				//@ if any change
				if (count($data) <> $numData) {
					file_put_contents($this->filePath, serialize($data), LOCK_EX);
				}
			}
		}
	}
 
	/**
	* Retrieve the number of online users.
	* @return int
	*/
	protected function CountUsers()
	{
		$content = file_get_contents($this->filePath);
 
		if (empty($content))
		{
			return 1;
		}
 
		$data = unserialize($content);
		$temp = array();
		for ($i=0; $i < count($data); $i++)
		{
			if (isset($data[$i]['ip_address']))
				array_push($temp, $data[$i]['ip_address']);
		}
 
		$num = count($temp);
 
		// Clean up memory
		$temp = $content = $data = null;
 
		return $num;
	}
}
// >> END CLASS File_UsersOnline

Then we have to include the above code in the pages where we want to display the total of visitors:

	require 'online-users.php';
/*
// USAGE:
*/
$foo = new File_UsersOnline( 'usersonline.txt' );
 
// Get the number of online users
$onlineUsers = $foo->CountOnlineUsers();
 
// Display the number of online users
echo "<p><em>Online users for the last 5 minutes:</em> <strong>{$onlineUsers}</strong></p>";

That’s all there is to it! If you want to download and use it on your website, follow this link.

Have fun!

About kos

I am a web developer and the author of IrisMVC framework, a framework built for RAD (rapid application development). I'm totally in love with PHP, MySQL, CSS and jQuery and I use them extensively, but I can do bits in other web technologies as well.
This entry was posted in Code for fun, Design Patterns, PHP and tagged , , . Bookmark the permalink.

2 Responses to Display the number of visitors to your website

  1. Pingback: Display the number of visitors to your website | IP address.co.uk

  2. This really is a little something I must find more information about, appreciate the post.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">