PHPとSQLでアクセスカウンターを自作してみた

プログラミング

こんにちは、未だ春休み延長戦のぴのです。

このホームページを始めてから1か月とちょっと経ちましたが、宣伝の甲斐もあって毎日それなりのアクセスをいただいております。これもみなさん(とTweetBotくん)のおかげです、ありがとうございます。

ところで、ホームページを運営しているとやはりアクセス数は気になるもの。実は今使用しているテーマ「Cocoon」はデフォルトでアクセス統計が取れる機能が付いております。管理人からはこんな感じでアクセス数を確認することができるんですね。

管理者側からはこう見える

しかしこの機能、各ページごとのアクセス数は表示してくれるのですが、全体のページの総アクセス数は表示してくれないんですよね。それに、訪問者がアクセス数を確認することができません。

そこで、例のごとくアクセスカウンターを自作することにしました。探せば同様のプラグインはありますが、せっかくなので勉強も兼ねて自作することにしました。「ランダム記事アクセスボタン」の時と同様に、ウィジェット形式で作っていきます。前回をまだご覧になっていない方はぜひ先にご覧ください。

アクセスカウンターを作る

データベースを確認する

あらかじめ「phpMyAdmin」等でデータベースにアクセスし、データを確認しておきます。今回必要な情報は、「アクセス統計のデータテーブル名」「日付のカラム名(と形式)」「アクセス数のカラム名」です。

確認すると、それぞれ「wp_cocoon_accesses」「date(Y-m-d)」「count」であることが確認できます。メモしておきましょう。

データベースに接続する処理を記述する

前回同様「Code Snippets」プラグインを利用して記述していきます。今回は「今日のアクセス数」と「全体のアクセス数」の情報が欲しかったので、SQLのSUM関数を使ってアクセス数(count)の総計を取得しています。例外処理についてやクエリ式を記述するときの注意などは参考サイトに詳しく書かれていたのでそちらをご参照ください。

try {
  $dbh = new PDO( //データベースに接続
      'mysql:host=localhost;dbname=okinotori;charset=utf8mb4', //データベース名など
      'okinotori', //ユーザー名
      '', //パスワード
      [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ] //オプション(エラー処理有)
  );
    
  date_default_timezone_set('Asia/Tokyo'); //タイムゾーンを東京に設定
  $today = date("Y-m-d"); //今日の日付
  $result = $dbh->prepare('SELECT SUM(count) FROM wp_cocoon_accesses WHERE date = ?'); //今日のアクセス数
  $result->execute([$today]);
  $result = $result->fetch();
  $todayCount = $result[0] ?? 0; //nullの場合は0

  $result = $dbh->query('SELECT SUM(count) FROM wp_cocoon_accesses'); //全体のアクセス数
  $result = $result->fetch();
  $totalCount = $result[0];

  echo "<span class=\"fa fa-bar-chart fa-fw\"></span><span>本日:\t".$todayCount."\t全体:\t".$totalCount."</span>";
} catch (PDOException $e) {
  exit($e->getMessage()); 
}

取得したデータはechoで出力します。前半のspanは統計っぽいアイコンを表示させるためのものです。詳しくは「Font Awesome」でググりましょう。

ウィジェット化する

前回と同じようにWP_Widgetを継承してウィジェット化します。

class AccessCounter extends WP_Widget{
  function __construct(){
    parent::__construct(
      'AccessCounter',
      'アクセスカウンター',
      array('description' => 'アクセスカウンターを表示するウィジェット')
    );
  }

  public function widget($args, $instance){
    echo $args['before_widget'];
    //ここから本体
    try {
      $dbh = new PDO(
        'mysql:host=localhost;dbname=okinotori;charset=utf8mb4',
        'okinotori',
        '',
        [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ]
      );
      date_default_timezone_set('Asia/Tokyo');
      $today = date("Y-m-d");
      $result = $dbh->prepare('SELECT SUM(count) FROM wp_cocoon_accesses WHERE date = ?');
      $result->execute([$today]);
      $result = $result->fetch();
      $todayCount = $result[0] ?? 0;		

      $result = $dbh->query('SELECT SUM(count) FROM wp_cocoon_accesses');
      $result = $result->fetch();
      $totalCount = $result[0];

      echo "<span class=\"fa fa-bar-chart fa-fw\"></span><span>本日:\t".$todayCount."\t全体:\t".$totalCount."</span>";
    } catch (PDOException $e) {
      exit($e->getMessage()); 
    }
    //ここまで本体
    echo $args['after_widget'];
  }
}

add_action(
  'widgets_init',
  function(){
    register_widget('AccessCounter');
  }
);

ウィジェットに設定する

管理画面からウィジェットとして配置しましょう。

完成

アクセスカウンターができた!!!!!

終わりに

SQLは知識としては知っていたのですが、今まで実践する機会がなかったので、今回のアクセスカウンターの作成はSQLの復習と実践ができてよかったと思います。

難点というかアクセスカウンターの宿命なのですが、アクセスカウンターを表示させるたびに処理が実行されるため、サーバーに負荷がかかることでしょうか。まあ負荷のことはもっとアクセス数が増えてから考えることにしましょう。

また、今回は気を付けて作ったつもりですが、特にユーザーからの入力を受け取るタイプのクエリ式を書くときは、SQLインジェクションされないように注意が必要ですね。管理人もTweetBotやらなんやら作っていますが、どこかに脆弱性がありそうで若干不安ですね。もし脆弱性をみつけたらコッソリ管理人にご連絡ください。

参考

コメント

タイトルとURLをコピーしました