Location: PHPKode > scripts > Count Script > count.class.php
<?
/*
Count and Online Class 0.1 by ming0070913
Counting how many times your website has been loaded and how many people are online.
It records the data with any specific time interval. It can also find out how many 
clicks or average online were there in a specific period of time. Together with the
function to analyse the records.
Since time() is used for UTC timezone, you need to set your timezone man manually.

Class Count:
- Count the clicks
	define('TABLE_COUNT', 'count');
		- the record table
Functions:
	__construct($step=3600, $keep=512, $timezone1="Asia/Taipei", $timezone2=8){
		- Settings
		- $step: how long do the counts seperate, second
		- $keep: how long will the records keep, day
		- $timezone1: set the timezone, do the same as php.ini
		- $timezone2: the local timezone, eg: +8 will be HK
	record($type=0, $allowrepeat=false)
		- Do counting
		- $type: type of the count
		- $allowrepeat: prevent count again
	read($group=-1, $records=0)
		- Read the records
		- $group: seperate the records into groups, second
		- $records: how many records will be loaded
	analyseMaxMin($group=0, $records=0)
		- Find out when is the max. and min.
		- $group: seperate the records into groups, second
		- $records: how many records will be loaded
	analyseAverage($group, $scale, $records=0)
		- Find out the average count of each period
		- eg: analyseAverage(86400, 3600) -> find out the average count in each hour
		- eg: analyseAverage(604800, 86400) -> find out the average count in each weekday
	install()
		- Create the tables

Class Online:
- Count the current connection
	define('TABLE_ONLINE', 'online');
		- the record table
	define('TABLE_ONLINETMP', 'online_tmp');
		- the tmp table
Functions:
	__construct($step=300, $keep=512, $buffer=180, $timezone1="Asia/Taipei", $timezone2=8)
		- Settings
		- $step: how long do the counts seperate, second
		- $keep: how long will the records keep, day
		- $buffer: how long will the people still been regarded as online
		- $timezone1: set the timezone, do the same as php.ini
		- $timezone2: the local timezone, eg: +8 will be HK
	record($type=0, $allowrepeat=false)
		- Do counting
		- $type: type of the count
		- $allowrepeat: prevent count again
	online($type=NULL)
		- Find out how many people online
	read($group=-1, $records=0)
		- Read the records, average online
		- $group: seperate the records into groups, second
		- $records: how many records will be loaded
	analyseMaxMin($group=0, $records=0)
		- Find out when is the max. and min., average online
		- $group: seperate the records into groups, second
		- $records: how many records will be loaded
	analyseAverage($group, $scale, $records=0)
		- Find out the average online of each period, needs at least $group time record
		- eg: analyseAverage(86400, 3600) -> find out the average online in each hour
		- eg: analyseAverage(604800, 86400) -> find out the average online in each weekday
	deleteExpired($onceonly=true)
		- Delete expired records in TABLE_ONLINE, automatic when it updates
		- $onceonly: prevent delete again
	deleteExpired2($onceonly=true)
		- Delete expired records in TABLE_ONLINETMP, automatic when it updates
		- $onceonly: prevent delete again
	getIP()
		- Get user IP
	install()
		- Create the tables
*/

define('TABLE_COUNT', 'count');
define('TABLE_ONLINE', 'online');
define('TABLE_ONLINETMP', 'online_tmp');

Class Recording{//Parent, should not be used
	protected $link, $step, $keep, $clean, $now, $count;
	
	public function read($group=-1, $records=0){
		$result = $this->query("SELECT * FROM `".($this->mode=="COUNT"?TABLE_COUNT:TABLE_ONLINE).
			"` ORDER BY `date` DESC, `type` ASC".($records>0?" LIMIT 0 , ".$records:"").";");
		while($row = mysql_fetch_array($result)){
			if($group>0){
				$date = floor(($row['date']*$this->step-$this->timezone)/$group);
				// if($this->mode=="ONLINE"){
					// $t[$date*$group][$row['type']] = 
						// ($t[$date*$group][$row['type']]*$times+$row['count'])/$times;
				// }else
				$t[$date*$group][$row['type']] += $row['count'];
			}else $t[$row['date']*$this->step][$row['type']] = $row['count'];
		}
		if($this->mode=="ONLINE"){
			$times = $group/$this->step;// inclues record that doesn't exist, count=0
			foreach($t as $date=>$types)
				foreach($types as $type=>$count)
					$tmp[$date][$type] = round($count/$times, 2);
			return $tmp;
		}
		return $t;
	}
	
	public function analyseMaxMin($group=0, $records=0){
		if($group>0) $data = $this->read($group, $records);
		else $data = $this->read(0, $records);
		
		foreach($data as $time=>$types){//get the max/min
			foreach($types as $type=>$count){
				if(!isset($t[$type]['min']) || $t[$type]['min']>$count) $t[$type]['min'] = $count;
				if($t[$type]['max']<$count)	$t[$type]['max'] = $count;
			}
		}
		foreach($data as $time=>$types){//find out the dates
			foreach($types as $type=>$count){
				if($t[$type]['min']==$count) $t[$type]['mindate'][] = $time;
				if($t[$type]['max']==$count) $t[$type]['maxdate'][] = $time;
			}
		}
		return $t;
	}
	
	public function analyseAverage($group, $scale, $records=0){
		$pieces = $group/$scale;
		if(!is_int($pieces) || $scale<$this->step) return false;
		$data = $this->read($scale, $records);
		
		foreach($data as $time=>$types)
			foreach($types as $type=>$count){
				$tmp[$type][(($time+$this->timezone)%$group)/$scale] += $count;
				if(!isset($d[$type]['min']) || $d[$type]['min']>$time)
					$d[$type]['min'] = $time; //get the stating dates of each type
				if($d[$type]['max']<$time) $d[$type]['max'] = $time; //get the ending dates of each type
			}
		
		$now = floor((time()+$this->timezone)/$scale)*$scale;
		foreach($d as $type=>$m){//get the total days passed
			$times_extra[$type]['head'] = $pieces-((($d[$type]['min']+$this->timezone)%$group)/$scale-1);
				// this-> (pass)''' ||||||| ||||||| '''(now)
			$times_extra[$type]['foot'] = ($now%$group)/$scale+1;
				// (pass)''' ||||||| ||||||| '''(now) <-this
			$times_total[$type] = floor(($now-$m['min'])/$group);
		}
		
		foreach($tmp as $type=>$ids){
			for($i=0;$i<$pieces;$i++){
				$times = $times_total[$type] +
					($i>=$times_extra[$type]['head'] ?1:0) +	// this-> (pass)''' ||||||| ||||||| '''(now)
					($i<=$times_extra[$type]['foot'] ?1:0);		// (pass)''' ||||||| ||||||| '''(now) <-this
				$t[$type][$i] = @round($ids[$i]/$times, 2);
			}
		}
		return $t;
	}
	
	public function deleteExpired($onceonly=true){
		if($onceonly && $this->clean) return false;
		$this->clean = true;
		return (bool) $this->query("DELETE FROM `".($this->mode=="COUNT"?TABLE_COUNT:TABLE_ONLINE).
			"` WHERE `date`*".$this->step."-".$this->timezone." < '".(time()-$this->keep)."';");
	}
	
	public function query($query){
		return mysql_query($query);
	}
	
	protected function createTable($sql, $table){
		if($this->query("SELECT * FROM `".$table."`;")!=false) return false;
		return (bool) @$this->query($sql);
	}
}
//-----------------------------------------------------------
Class Count extends Recording{
	protected $mode = "COUNT";
	
	function __construct($step=3600, $keep=512, $timezone1="Asia/Taipei", $timezone2=8){
		date_default_timezone_set($timezone);
		$this->timezone = $timezone2*3600;
		$this->step = $step;
		$this->keep = $keep*86400;
		$this->now = floor((time()+$timezone2*3600)/$step);
		//echo date('Y/n/j H:i:s', $this->now*$this->step-$this->timezone);
	}
	
	public function record($type=0, $allowrepeat=false){
		if(!$allowrepeat && $this->count[$type]!=NULL) return $this->count[$type];
		$result = $this->query("SELECT `count` FROM `".TABLE_COUNT."` 
			WHERE `date` = '".$this->now."' AND `type` = '".$type."';");
		$result = @mysql_fetch_array($result);
		if(!$result){
			$this->deleteExpired();
			$this->count[$type] = 1;
			if(!$this->query("INSERT INTO `".TABLE_COUNT."`(`type`,`date`,`count`)
				VALUES('".$type."', '".$this->now."', '1');")) return false;
		}else{
			$this->count[$type] = $result["count"]+1;
			if(!$this->query("UPDATE `".TABLE_COUNT."` SET `count` = '".$this->count[$type].
				"' WHERE `date` = '".$this->now."' AND `type` = '".$type."';")) return false;
		}
		return $this->count[$type];
	}
	
	public function install(){
		return $this->createTable("
			CREATE TABLE IF NOT EXISTS `".TABLE_COUNT."` (
				`type` smallint(2) NOT NULL,
				`date` int(10) NOT NULL,
				`count` int(8) NOT NULL,
				PRIMARY KEY (`type`,`date`)
			);", TABLE_COUNT);
	}
}

//-----------------------------------------------------------
Class Online extends Recording{
	protected $mode = "ONLINE";
	private $recorded, $ip, $buffer, $clean2;
	
	function __construct($step=900, $keep=512, $buffer=180, $timezone1="Asia/Taipei", $timezone2=8){
		date_default_timezone_set($timezone);
		$this->timezone = $timezone2*3600;
		$this->step = $step;
		$this->keep = $keep*86400;
		$this->now = floor((time()+$timezone2*3600)/$step);
		//echo date('Y/n/j H:i:s', $this->now*$this->step-$this->timezone);
	}
	
	public function record($type=0, $allowrepeat=false){
		if(!$allowrepeat && $this->count[$type]) return false;
		$this->count[$type] = true;
		$result = @mysql_num_rows($this->query("SELECT * FROM `".TABLE_ONLINETMP.
			"` WHERE `ip` = '".$this->getIP()."' AND `type` = '".$type."';"));
		if(!$result){
			if(!$this->query("INSERT INTO `".TABLE_ONLINETMP."`(`type`, `ip`,`update`) VALUES('".
				$type."', '".$this->getIP()."', '".time()."');")) return false;
		}else{
			if(!$this->query("UPDATE `".TABLE_ONLINETMP."` SET `update` = '".time().
				"' WHERE `ip` = '".$this->getIP()."' AND `type` = '".$type."';")) return false;
		}
		$this->deleteExpired();
		
		$result = @mysql_num_rows($this->query("SELECT * FROM `".TABLE_ONLINE.
			"` WHERE `date` = '".$this->now."' AND `type` = '".$type."';"));
		if(!$result){
			if(!$this->query("INSERT INTO `".TABLE_ONLINE."`(`type`, `date`, `count`) VALUES('".
				$type."', '".$this->now."', '".$this->online($type)."');")) return false;
			$this->deleteExpired2();
		}
		return true;
	}
	
	public function online($type=NULL){
		if(!is_int($type)){
			$result = $this->query("SELECT `type`, COUNT(*) COUNT FROM `".TABLE_ONLINETMP.
				"` GROUP BY `type` ORDER BY `type` ASC;");
			while($row = mysql_fetch_array($result))
				$t[$row['type']] = $row['COUNT'];
			return $t;
		}else{
			$row = @mysql_fetch_array($this->query("SELECT COUNT(*) COUNT FROM `".TABLE_ONLINETMP.
				"` WHERE `type` = '".$type."';"));
			return $row['COUNT'];
		}
	}
	
	public function deleteExpired2($onceonly=true){
		if($onceonly && $this->clean2) return false;
		$this->clean2 = true;
		return (bool) $this->query("DELETE FROM `".TABLE_ONLINETMP."` WHERE `update` < '".
			(time()-$this->buffer)."';");
	}
	
	public function install(){
		return (
		$this->createTable("
			CREATE TABLE IF NOT EXISTS `".TABLE_ONLINE."` (
				`type` smallint(2) NOT NULL,
				`date` int(10) NOT NULL,
				`count` int(8) NOT NULL,
				PRIMARY KEY (`type`,`date`)
			);", TABLE_ONLINE)
		&&
		$this->createTable("
			CREATE TABLE IF NOT EXISTS `".TABLE_ONLINETMP."` (
				`type` smallint(2) NOT NULL,
				`ip` CHAR( 15 ) NOT NULL ,
				`update` INT NOT NULL ,
				PRIMARY KEY (`type`,`ip`)
			);", TABLE_ONLINETMP)
		);
	}
	
	public function getIP(){
		if($this->ip) return $this->ip;
		if(empty($_SERVER['HTTP_X_FORWARDED_FOR'])) $this->ip = $_SERVER['REMOTE_ADDR'];
		else{
			$ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
			//briefly check the ip to prevent fake ip
			if(preg_match('/(^[0-9]{1,3}\.){4}$/', $ip[0].'.')) $this->ip = $ip[0];
			else $this->ip = $_SERVER['REMOTE_ADDR'];
		}
		return $this->ip;
	}
}
?>
Return current item: Count Script