一覧 |
コード登録画面
アクセスカウンタ [ 2005年04月29日 ]
<?php
/*
* Linux/Windowsで利用可能なアクセスカウンタです.
* 同一のPCによる連続アクセスはカウントされないようになっています.
*
* 下準備:
* 1:このファイルがあるディレクトリに data というディレクトリを作ります
* 2:data/ の権限を777に設定します(Linuxの場合)
*
* 利用例:
* ------------------------------------
* <?php
* require_once('count.php'); // このファイルを読み込む
* step(); // カウンタを1増やす
* ?>
* <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
* <html lang="ja">
* <head>(中略)</head>
* <body>
* <ul>
* <li>今日: <?= today() ?></li>
* <li>昨日: <?= yesterday() ?></li>
* <li>合計: <?= total() ?></li>
* </ul>
* </body>
* </html>
* ------------------------------------
*/
/**
* このファイルがあるディレクトリの相対パスです.
* 別のディレクトリから参照する際は、この変数をオーバーライドする必要があります.
* 末尾に '/' は付けないで下さい.
*/
$COUNT_HOME_DIR = '';
/**
* アクセスをカウントします.
* このアクセスが、直前のアクセスと同一でなければカウントします.
*/
function step(){
$access_counter = get_access_counter();
$access_counter->step();
}
/**
* 今日のアクセス数を返します.
*/
function today(){
$access_counter = get_access_counter();
$today = new date();
$today_value = $access_counter->get_data($access_counter->log_name($today));
return $today_value ? intval($today_value) : 0;
}
/**
* 昨日のアクセス数を返します.
*/
function yesterday(){
$access_counter = get_access_counter();
$yesterday = new date();
$yesterday->date --;
$yesterday->adjust();
$y_value = $access_counter->get_data($access_counter->log_name($yesterday));
return $y_value ? intval($y_value) : 0;
}
/**
* 累計のアクセス数を返します.
*/
function total(){
$access_counter = get_access_counter();
$total_value = $access_counter->get_data('total.txt');
return $total_value ? intval($total_value) : 0;
}
function get_access_counter(){
static $access_counter;
if(!isset($access_counter)){
$access_counter = new access_counter();
}
return $access_counter;
}
/**
* アクセスカウンターを管理するクラスです.
*/
class access_counter{
/**
* 最新のアクセスを表す access オブジェクトです.
*/
var $current_access;
/**
* 直前のアクセスを表す access オブジェクトです.
* 存在しない場合は NULL になります.
*/
var $last_access;
/**
* 新しい access_counter オブジェクトを構築します.
*/
function access_counter(){
$this->current_access = new access();
$this->last_access = $this->get_last_access();
}
/**
* 直前のアクセスを access オブジェクトとして返します.
* 存在しないか、データが不正な場合は NULL を返します.
*/
function get_last_access(){
$ip = $this->get_data('last-ip.txt');
if(!$ip) return NULL;
$date = $this->get_data('last-date.txt');
if(!$date) return NULL;
$access = @new access($ip, new date($date));
return $access;
}
/**
* ファイルの中身(1行目)を返します.
* ファイルが存在しない場合は FALSE を返します.
*/
function get_data($filename){
global $COUNT_HOME_DIR;
$data = @file($COUNT_HOME_DIR.'/'.$filename);
return (isset($data)) ? trim($data[0]) : FALSE;
}
/**
* ファイルの中身(1行しか存在しないもの)を更新します.
* ファイルが存在しない場合は新しく作成を試みます.
*/
function set_data($filename, $data){
global $COUNT_HOME_DIR;
$fp = fopen($COUNT_HOME_DIR.'/'.$filename, 'w');
fwrite($fp, $data);
fclose($fp);
@chmod($COUNT_HOME_DIR.'/'.$filename, 0666);
}
/**
* カウンタを回します.
*/
function step(){
// このアクセスが直前のアクセスと同じ場合は何もしません.
if($this->current_access->equals($this->last_access)) return;
// 今日のカウントを記録します.
$todaylog = $this->log_name($this->current_access->date);
$today_value = $this->get_data($todaylog);
$today_count = $today_value ? intval($today_value) : 0;
$today_count ++;
$this->set_data($todaylog, $today_count);
// 合計のカウントを記録します.
$total_value = $this->get_data('total.txt');
$total = $total_value ? intval($total_value) : 0;
$total ++;
$this->set_data('total.txt', $total);
// このアクセスに関する情報を記録します.
$this->set_data('last-ip.txt', $this->current_access->ip);
$this->set_data('last-date.txt', $this->current_access->date->to_string());
}
/**
* 指定された日付におけるアクセスログのファイル名を返します.
*/
function log_name($date){
return 'data/'.$date->to_string().'.txt';
}
}
/**
* ユーザーのアクセスを表すクラスです.
* IPアドレスとアクセスした日付を保持します.
*/
class access{
/**
* このアクセスのIPアドレスです.
*/
var $ip;
/**
* このアクセスの年月日です.
*/
var $date;
/**
* 新しい access オブジェクトを構築します.
* 引数が指定されなかった場合、このファイルへのアクセスを表す
* access オブジェクトを構築します.
* @param $date アクセス日時を表すdateオブジェクト
*/
function access($ip = NULL, $date = NULL){
$this->ip = (isset($ip)) ? $ip : $_SERVER['REMOTE_ADDR'];
$this->date = (isset($date)) ? $date : new date();
}
/**
* 指定された access オブジェクトが、このオブジェクトと同じかどうかを返します.
* IPアドレスと、最後にアクセスした日付が同じ場合に TRUE を返します.
*/
function equals($access){
if(!is_a($access, 'access')) return FALSE;
return ($this->ip == $access->ip) && ($this->date == $access->date);
}
/**
* このaccessの文字列表現を返します.
*/
function to_string(){
return '[IP='.$this->ip.',DATE:'.$this->date->to_string().']';
}
}
/**
* 年月日の情報を保持するクラスです.
*/
class date{
/**
* 年を表す整数です.
*/
var $year;
/**
* 月を表す整数です.
*/
var $month;
/**
* 日を表す整数です.
*/
var $date;
/**
* 指定された年月日を示す date オブジェクトを構築します.
* 引数が指定されない場合、保持する年月日は現在のものとなります.
* @param $format 'YYYY-mm-dd' 形式の文字列
*/
function date($format = NULL){
if(isset($format)){
$year = substr($format, 0, 4);
$month = substr($format, 5, 2);
$date = substr($format, 8, 2);
if(is_numeric($year) && is_numeric($month) && is_numeric($date)){
$this->year = intval($year);
$this->month = intval($month);
$this->date = intval($date);
$this->adjust();
}else{
trigger_error('不正なフォーマットです."YYYY-mm-dd"という書式でなければなりません('.$format.')');
}
}
else{
$this->year = date('Y');
$this->month = date('m');
$this->date = date('d');
}
}
/**
* 年月日の不整合を調整します.
* 2005年4月31日 → 2005年5月1日
* 2005年1月-1日 → 2004年12月30日
* 2004年14月31日 → 2005年2月31日 → 2005年3月3日
*/
function adjust(){
if($this->month < 1){
$m_value = abs($this->month);
$year_amount = $m_value / 12 + 1;
$this->year -= $year_amount;
$this->month = 12 - ($m_value % 12);
$this->adjust();
return;
}
if(12 < $this->month){
$year_amount = $this->month / 12;
$this->year += $year_amount;
$this->month = $this->month % 12;
$this->adjust();
return;
}
if($this->date < 1){
while($this->date < 1){
$this->date_move_up();
}
return;
}
if($this->get_date_count() < $this->date){
while($this->get_date_count() < $this->date){
$this->date_move_down();
}
return;
}
}
/**
* 日が1より小さい場合の繰り上げ処理です.
*/
function date_move_up(){
$this->month --;
if($this->month == 0){
$this->month = 12;
$this->year --;
}
$this->date += $this->get_date_count();
}
/**
* 日が、その月の日数より大きい場合の繰り下げ処理です.
*/
function date_move_down(){
$this->date -= $this->get_date_count();
$this->month ++;
if($this->month == 13){
$this->month = 1;
$this->year ++;
}
}
/**
* 指定された日付とこの日付が等しいかどうかを返します.
*/
function equals($date){
if(!is_a($date, 'date')) return FALSE;
return
($this->year == $date->year) &&
($this->month == $date->month) &&
($this->date == $date->date);
}
/**
* このdate の文字列表現を返します.
*/
function to_string(){
$year = str_pad($this->year, 4, '0', STR_PAD_LEFT);
$month = str_pad($this->month, 2, '0', STR_PAD_LEFT);
$date = str_pad($this->date, 2, '0', STR_PAD_LEFT);
return $year .'-'.$month.'-'.$date;
}
/**
* この date がうるう年かどうかを返します.
* - 4で割り切れるはうるう年である
* - ただし、100で割り切れる年はうるう年ではない
* - ただし、400で割り切れる年はうるう年である
*/
function is_leap_year(){
if($this->year % 4 != 0){
return FALSE;
}else if($this->year % 100 != 0){
return TRUE;
}else{
return ($this->year % 400 == 0);
}
}
/**
* このdateが示す月の日数を返します.
*/
function get_date_count(){
switch($this->month){
case 1:
return 31;
case 2:
return ($this->is_leap_year()) ? 29 : 28;
case 3:
return 31;
case 4:
return 30;
case 5:
return 31;
case 6:
return 30;
case 7:
return 31;
case 8:
return 31;
case 9:
return 30;
case 10:
return 31;
case 11:
return 30;
case 12:
return 31;
}
}
}
?>
投稿者:Hawk