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

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

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

みやびプリン 500 316

144 144

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

あぁ、今年ももう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:

コメントする

ページトップへ戻る