(8) SQLiteでアクセスカウンタ作成 #3 (二重カウント回避)

投稿者: | 2016年10月23日

1,700 views

この記事は最終更新から 2598日 が経過しています。

やってみたいこと

「(7) SQLiteでアクセスカウンタ作成 #2」 を改造し、同じIPアドレスからのアクセスは1日に1回だけカウントするように変更する。
00007_1

実行サンプルはこちらです。
//www.dogrow.net/php/sample/00008/

プログラム作成

index.php

「(7) SQLiteでアクセスカウンタ作成 #2」と同じ

counter_img.php

「(7) SQLiteでアクセスカウンタ作成 #2」と同じ

CCounter.php

アクセスログを記録するためのテーブル acclog を新規追加した。

<?php
class CCounter {
  private $m_db;        // SQLite3 instance
  private $m_db_fpath;  // DBファイルパス

  //////////////////////////////////////////////////////////////////////////////
  // コンストラクタ
  function __construct( $fpath = "cnt.db" ) {
    $this->m_db = NULL;
    $this->m_db_fpath = $fpath;
  }

  //////////////////////////////////////////////////////////////////////////////
  // DB接続
  function connect_db(){
    if($this->m_db == NULL){
      // DBファイル存在確認
      $isDbExist = file_exists($this->m_db_fpath);
      try {
        // DB接続
        $this->m_db = new SQLite3($this->m_db_fpath);
        $this->m_db->enableExceptions(TRUE);
        // DBは新規作成?
        if($isDbExist === FALSE){
          // カウント値用テーブルを作成し、カウント値を0で初期化
          $this->m_db->exec("CREATE TABLE `mytbl` (`cnt` INTEGER, `dt_lastacc` INTEGER);");
          $this->m_db->exec("INSERT INTO `mytbl` (`cnt`,`dt_lastacc`) VALUES(0, ".time().");");
          // アクセスログ用テーブルを作成
          $this->m_db->exec("CREATE TABLE `acclog` (`ipaddr` TEXT, `accfrom` TEXT, `acctime` TEXT);");
        }
      }catch(Exception $e){
        echo "[".__LINE__."] Caught exception: ".$e->getMessage();
      }
    }
  }

  //////////////////////////////////////////////////////////////////////////////
  // DB切断
  function disconnect_db(){
    if($this->m_db != NULL){
      $this->m_db->close();
      $this->m_db = NULL;
    }
  }

  //////////////////////////////////////////////////////////////////////////////
  // カウンタ更新&更新値を取得
  function count_up(){
    $cnt = 0;
    if($this->m_db != NULL){
      // 日付変更ならばアクセスログを削除
      $this->clear_acclog_if_date_changed();
      try {
        // 二重カウントチェック
        if($this->is_ipaddr_exist() === FALSE){
          $dt_now = time();
          // カウンタをインクリメント
          $this->m_db->exec("UPDATE `mytbl` SET `cnt`=`cnt`+1,`dt_lastacc`='$dt_now';");
          // アクセスログ更新
          $this->m_db->exec("INSERT INTO `acclog` (`ipaddr`,`accfrom`,`acctime`) VALUES('".$_SERVER["REMOTE_ADDR"]."','','$dt_now');");
        }
        // カウンタの値を取得
        $rs = $this->m_db->query("SELECT `cnt` FROM `mytbl`;");
        $row = $rs->fetchArray();
        $cnt = $row['cnt'];
      }catch(Exception $e){
        echo "[".__LINE__."] Caught exception: ".$e->getMessage();
      }
    }
    return $cnt;
  }

  //////////////////////////////////////////////////////////////////////////////
  // 日付変更時にアクセスログをクリア
  function clear_acclog_if_date_changed(){
    if($this->m_db != NULL){
      $day_now = strftime("%G%m%d", time());
      try {
        // アクセスログ最終更新日を取得
        $rs = $this->m_db->query("SELECT `dt_lastacc` FROM `mytbl`;");
        $row = $rs->fetchArray();
        $day_last = strftime("%G%m%d", $row['dt_lastacc']);
        // 日付変更?
        if($day_now != $day_last){
          // アクセスログを削除
          $this->m_db->exec("DELETE FROM `acclog`;");
        }
      }catch(Exception $e){
        echo "[".__LINE__."] Caught exception: ".$e->getMessage();
      }
    }
  }

  //////////////////////////////////////////////////////////////////////////////
  // 二重カウントチェック
  function is_ipaddr_exist(){
    $ret = FALSE;
    if($this->m_db != NULL){
      try {
        $ipaddr = $_SERVER["REMOTE_ADDR"];
        $rs = $this->m_db->query("SELECT COUNT(*) FROM `acclog` WHERE `ipaddr`='$ipaddr';");
        $row = $rs->fetchArray();
        if($row[0] > 0){
          $ret = TRUE;      // アクセス元IPアドレスが登録済み。
        }
      }catch(Exception $e){
        echo "[".__LINE__."] Caught exception: ".$e->getMessage();
      }
    }
    return $ret;
  }
}
?>

 
実行サンプルはこちらです。
//www.dogrow.net/php/sample/00008/


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)