【コピペで使える】PHP/Ajaxを使った視聴者数表示機能実装サンプル

はじめに

YouTubeライブ配信やニコ生で表示される視聴者数をウェブページで実現する機能実装を考えてみました。

ウェブページの閲覧数などは基本的には過去の累積となりますが、ここでは今現在リアルタイムでそのページを閲覧している人の数を刻一刻と表示してゆく処理を目指します。

チャットや掲示板サイトなど、参加を促進したいサイトに導入頂くと効果があるかもしれません。
 

処理の概要

閲覧者数を取得するにはユニークアクセスを取得する必要があります。

同じユーザーのアクセスを重複してカウントしてはならないので、これを判別する情報としてIPアドレスを使用します。

ページ上で定期的にページのURIとIPアドレスのふたつの情報を取得しデータベースに格納、さらに、その情報を定期的に集計し、1分間内に同一のページを見ているIPアドレスがいくつあるかをカウントし表示数としてページに表示するという処理を目指したいと思います。
 

処理のフロー

以下、今回の処理のフローです。

ユーザーがページへアクセス

Ajaxで定期的にアクセス情報を登録

Ajaxで定期的に閲覧者数(一定時間内のユニークアクセス数)を取得

JQueryでHTMLに取得した閲覧者数を表示

 

ファイル構成

  • ・db.php…データベース関連処理
  • ・count.php…カウントを表示するページ
  • ・set_count.php…データベースにアクセス情報を登録
  • ・get_count.php…データベースから閲覧者数を取得

 

実装(コーディング)サンプル

DB

logsテーブル

・id(INT)
・uri(TEXT)
・ipaddress(TEXT)
・created(TIMESTAMP)

PHPファイル

db.php


<?php
// DB接続情報
define("DB_HOST", "【データベースサーバー名】");
define("DB_USER", "【ユーザー名】");
define("DB_PASS", "【パスワード】");
define("DB_NAME", "【データベース名】");
// アクセスログの格納
function setLogs($uri, $ipaddress){
  // データベースからリスト取得
  $db = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
  // 文字コードセット
  $db->query('SET NAMES utf8');
  // SQL文作成
  $sql = "INSERT INTO logs (uri, ipaddress) VALUES (:uri, :ipaddress);";
  // クエリ
  $stt = $db->prepare($sql);
  // 変数設定
  $stt->bindParam(':uri', $uri);
  $stt->bindParam(':ipaddress', $ipaddress);
  // クエリ実行
  $ret = $stt->execute();
  return $ret;
}
// 閲覧者数の取得(1分以内のユニークアクセスを取得)
function getLogs($uri){
  // データベースからリスト取得
  $db = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
  // 文字コードセット
  $db->query('SET NAMES utf8');
  // SQL文作成
  $sql = "SELECT COUNT(*) as cnt FROM logs WHERE uri = :uri AND created > current_timestamp + interval -1 minute GROUP BY ipaddress";
  // クエリ
  $stt = $db->prepare($sql);
  // 変数設定
  $stt->bindParam(':uri', $uri);
  // クエリ実行
  $stt->execute();
  // 結果抽出
  $row = $stt->fetch();
  // 返却
  return $row['cnt'];
}
?>

set_count.php


<?php
require_once('./db.php'); // db.phpファイルの読み込み(同一階層格納時)
setLogs($_GET['uri'], $_GET['ipaddress']); // アクセスログを登録
?>

get_count.php


<?php
require_once('./db.php'); // db.phpファイルの読み込み(同一階層格納時)
echo getLogs($_GET['uri']); // 1分以内のユニークアクセス数を取得してajaxに返す
?>

HTML&JQueryファイル

count.php


<?php
require_once('./db.php'); // db.phpファイルの読み込み(同一階層格納時)
$uri = $_SERVER["REQUEST_URI"]; // アクセスしたページのURI
$ipaddress = $_SERVER["REMOTE_ADDR"]; // IPアドレス取得
?>
<html>
<head>
<script>
<!--
/* 定期的にcountAll関数を実行 */
setInterval("countAll()",10000);
/* アクセス情報の登録と取得を行う */
function countAll(){
  setCount();
  getCount();
}
/* アクセスユーザーのログを記録 */
function setCount(){
  jQuery( function() {
    jQuery.ajax({
      url: './set_count.php',
      data: {
        uri: '<?php echo $uri; ?>',
        ipaddress: '<?php echo $ipaddress; ?>'
      },
      success: function( data ) {
      },
      error: function( data ) {
      }
    });
  });
}
/* アクセスユーザーのログを取得 */
function getCount(){
  jQuery( function() {
    jQuery.ajax({
      url: './get_count.php',
      data: {
        uri: '<?php echo $uri; ?>'
      },
      success: function( data ) {
        jQuery('#show-count').html(data);
      },
      error: function( data ) {
      }
    });
  });
}
</script>
</head>
</body>
<!-- 閲覧者数表示 -->
現在の視聴者数:<div id="show-count"></div>
</body>
</html>

 

まとめ

現在の閲覧者数を出すだけの処理ですが、意外と複雑な内容となりました。

このサンプルではリフレッシュ処理がないため、logsテーブルのレコード数は時間とともに膨大となってしまいますので、実利用時は必ずテーブルのクリア(24時間に一回など)をするようにしてください。

※内容に不備がある場合はご指摘頂けますと幸いです。