PHP アクセスカウンター 二重カウント防止付き

謎のプリン語る。
プログラミングの役立つ情報とか、どうでもいい雑談とか書いてます。
一人書く人増えました。

PHP アクセスカウンター 二重カウント防止付き

2015年09月18日

みやびプリン 500 316

144 144

※この記事は7年以上前の記事です。
現在は状況が異なる可能性がありますのでご注意ください。

あぁ、今年ももう9月。4分の3が終わってまった。

いつもならもうか・・・、となりますが、
今年はサイトのリニューアルもできたのでよしとします。
(まだ終わってないって)

さて、サイトのアクセスカウンター、ずっとYahooのジオシティーズのを使ってたのですが、
そのサービスがいつのまにか終了しておりましたので・・・、
自作しました。ええ、しましたとも。
一応、二重カウント防止付き。
仕様としては、同IPは、アクセスから日付変更されるまで、二重カウントしない、です。
(例えば、8月25日にアクセスしたIPは、8月26日00時まで、二重カウントしない・・・って感じ)

というわけで、ソースコードを公開しようかな、とね。さてさて

まずは、下記ファイルを適当にテキストエディタかなんかで作っておく。

・countor.php ・count_no.dat
・first_access_time.dat
・ip_list.dat

とりあえず、全部空でよし。
ファイル名もなんでもよし。

だが、ひとまず、count_no.dat(カウントの数値が入るデータ)には適当に初期数値でも入れておくといい。
0でもいい。
では、スクリプトファイルである、countor.phpの中身を書いていこう。

<?php
//カウンター桁数
define('DIGIT_NO', 7);

//datファイル読み込み
global $countDataFile;
global $firstAccessTimeFile;
global $ipListFile;

$countDataFile = dirname(__FILE__) . '/count_no.dat';
$firstAccessTimeFile = dirname(__FILE__) . '/first_access_time.dat';
$ipListFile = dirname(__FILE__) . '/ip_list.dat';

//IPチェックするかどうか
$doubleCheck = 1;

//ファイルの中身を配列にして変数に格納する。(行ごとに分けられて格納される)
$countData = file($countDataFile);
$firstAccessTimeData = file($firstAccessTimeFile);
$ipListData = file($ipListFile);

//必要データを変数に格納
global $countNo;
global $firstTimeStamp;
global $ipList;

//現在カウントを数値で取得
$countNo = intval($countData[0]);
//その日の最初のアクセス時間を格納する変数宣言
$firstTimeStamp = '';
//タイムdatにタイムが入っていれば、タイムスタンプ格納
if (count($firstAccessTimeData) > 0) {
  $firstTimeStamp = $firstAccessTimeData[0];
}
//その日のIPリストの変数と格納
$ipList = array();
if (count($ipListData) > 0) {
  $ipList = explode('<>', $ipListData[0]);
}

//今日のタイムスタンプ
$toDay = time();
//24時間後のタイムスタンプを格納
$nextDayBefore = intval($toDay) + 86400;

//年月日を各変数に格納
$nextDayTextYear = date('Y', $nextDayBefore);
$nextDayTextMonth = date('m', $nextDayBefore);
$nextDayTextDay = date('d', $nextDayBefore);

//次の日のテキストを格納 ex)2015-09-03
$nextText = date($nextDayTextYear . '-' . $nextDayTextMonth . '-' . $nextDayTextDay);
//次の日0時のタイムスタンプを取得
$nextDayUsed = strtotime(date($nextText . ' 00:00:00'));

//ファイルに書き込むメソッド
function fileReadFunc($fileUrl, $readText){
  $fileOpen = fopen($fileUrl, 'w');
  // ファイルロック
  flock($fileOpen, LOCK_EX);

   if (strlen($readText) > 0) {
     //書き込み
     fputs($fileOpen, $readText);
   } else {
     //ファイルを空にする
     ftruncate($fileOpen, 0);
  }

  // ロック解除
  flock($fileOpen, LOCK_UN);
  // ファイルを閉じる
  fclose($fileOpen);
}

//日付変更が行われたかをチェックするフラグ
$dayChange = false;

//一日の初期アクセスを格納
if (strlen($firstTimeStamp) > 0) {
  //datにタイムスタンプがある
  if ($firstTimeStamp <= $toDay) {
    //次の日タイムスタンプより今日のタイムスタンプが大きい
    $dayChange = true;
    //ファイル書き込み
    fileReadFunc($firstAccessTimeFile, $nextDayUsed);
  }
} else {
  //datファイルに文字列入ってない
  $dayChange = true;
  //ファイルに書き込み
  fileReadFunc($firstAccessTimeFile, $nextDayUsed);
}

//ipListをリセット
if ($dayChange) {
  //日付変更が行われていれば、1日のIPアクセスリストをリセット
  if (count($ipList) > 0) {
    //IPdatに文字列あれば、空にする
    fileReadFunc($ipListFile, '');
  }
  //IPリスト変数をリセット
  $ipList = array();
}

//IPリストにIPをいれ、ファイルに書き込むメソッド
function ipPush(){
  global $ipList;
  global $ipListFile;

  //IPリストに、現IPを格納
  array_push($ipList, $_SERVER['REMOTE_ADDR']);
  $insertIp = implode('<>', $ipList);
  //ファイルに書き込み
  fileReadFunc($ipListFile, $insertIp);
}


//カウントアップするかのフラグ
$countUP = true;

if (count($ipList) > 0) {
  foreach ($ipList as $value) {
    if ($_SERVER['REMOTE_ADDR'] == $value) {
      //IPリストにあるIPならカウントをしない設定
      $countUP = false;
      break;
    }
  }
} else {
  //IPリストが空なら、IP追加
  ipPush();
}

//最終的なカウンター数値
$nextNo = $countNo;

if ($countUP) {
  //カウントアップを実行
  $nextNo = $countNo + 1;
  fileReadFunc($countDataFile, $nextNo);
  if (count($ipList) > 0) {
    ipPush();
  }
 }

echo number_format($nextNo);

して、こいつを表示させたいPHPページから読み込む

<?php
include('/サーバールートからの絶対パス/サイトルートからのディレクトリ/countor.php');
?>

とまぁ、こんな感じ。
だいたいは、コメントを見ていただければわかると思いますが、
二重カウント防止のポイントは、
まずは、最初のアクセスから次の日の00時を取得し、datファイルに書き込み
次にIPリストdatに書き込みし、
それを元に、IPの二重アクセスを防止。
もし日付変更されていたら、IPリストdatファイルを空にする。
こうすれば、その日の間は同IPでは二重カウントはされなく、日付が変更されるとリセットされる。
(最初、ここらをSessionでやろうとしたけど、有効期限などをうまくできなかった・・・。)

これで、世の多くのアクセスカウンターの仕様とだいたい一緒にすることができた。

まぁ、最も、アクセスカウンター自体が懐かしいものなんだけね・・・。
ここ何年かで随分減ったしね。アクセス解析は、アナリィティクスでできるしね・・・。

しかし、いいワークショップになりました。

セキュリティ??
んなもん知るか

トラックバック(0)

トラックバックURL:

コメントする

ページトップへ戻る