[[PukiWiki]]

#contents

* 概要 [#u24a71e4]
MySQLを使ったpukiwiki用のアクセスカウンターです。
一言でいえば、pukiwikiのページ名ごとに、アクセス情報を保存しているだけです。

* インストール [#va5b3c26]
以下の手順でインストールできます。

** 免責 [#g4423f14]
本スクリプトをご利用なさる場合は、万一トラブルが発生しても責任は負いかねますので、自己責任にてご利用ください。

** ダウンロード [#a1402b24]
このページに添付してある「pukiwiki_db_counter.zip」をダウンロードして解凍します。

&ref(pukiwiki_db_counter.zip);

** データベースのテーブル作成 [#oaca2e7a]
MySQLにアクセスカウンター用のテーブルを作ります。
以下のSQLは、MySQL4.1以上でOKです。(MySQL5.5でOKでした。)
MySQL4.0以下だと、「CHARSET=utf8」は文法エラーになるので削ります。

[pukiwiki_page]テーブル
#code(sql){{
CREATE TABLE IF NOT EXISTS `pukiwiki_page` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `page` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
}}

[pukiwiki_access]テーブル
#code(sql){{
CREATE TABLE IF NOT EXISTS `pukiwiki_access` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `page_id` int(11) NOT NULL,
  `ip` varchar(32) NOT NULL,
  `date` date NOT NULL,
  `time` time NOT NULL,
  PRIMARY KEY (`id`),
  KEY `page_id_date` (`page_id`,`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
}}

**設定の編集 [#h152dbec]
解凍したフォルダ「lib」の中にある「_db_counter.php」で、設定を編集します。

#code(php){{
//-----------------------------------------------
// config
//-----------------------------------------------

// DB
define('DB_USER',	'mysql_username');
define('DB_PASS',	'mysql_password');
define('DB_HOST',	'localhost');
define('DB_NAME',	'mysql_dbname');
define('DB_CHAR',	'UTF-8');
define('TBL_PAGE',	'pukiwiki_page');
define('TBL_ACCESS',	'pukiwiki_access');

// URL
define('DOMAIN',	'www.mydomain.com');
define('SCRIPT',	'/pukiwiki/index.php');

// ranking
define('TERM',	10);	// 集計期間(日)
define('NUM',	10);	// 順位数(例:10位までなら10)
}}

以下の内容を設定してください。

| 設定項目 | 内容 |h
| DB_USER | MySQLを利用するユーザー名 |
| DB_PASS | MySQLを利用するパスワード |
| DB_HOST | MySQLのホスト名(通常は「localhost」)|
| DB_NAME | MySQLのデータベース名 |
| DB_CHAR | MySQLの文字コード(通常は「UTF-8」)|
| TBL_PAGE | pukiwikiのページ名を保存するテーブル名(通常は「pukiwiki_page」)|
| TBL_ACCESS | pukiwikiのアクセスログを保存するテーブル名(通常は「pukiwiki_access」)|
| DOMAIN | pukiwikiが設置してあるWebサイトのドメイン名 |
| SCRIPT | pukiwikiのスクリプトまでのパス |
| TERM | アクセスカウンターで表示する集計期間の日数 |
| NUM | アクセスカウンターで表示する順位数(例:上位10位までなら10)|

**アクセスカウンター [#e928183e]
「skin/pukiwiki.skin.php」にアクセスカウンターを呼び出すコードを追記します。

#code(php){{
<?php
require_once('lib/_db_counter.php');
?>
}}

通常は、メニューバーの表示部分の下部に追記すればOKです。

#code(php){{
<div id="menubar">
<?php
if (arg_check('read') && exist_plugin_convert('menu')) {
	echo do_plugin_convert('menu');
	
	require_once('lib/_db_counter.php'); // アクセスカウンター
	
}
?>
</div>
}}

**ファイルの配置 [#yadff898]
アクセスカウンター用のフォルダとファイルを、Webサーバー内のpukiwikiを設置したディレクトリにアップロードします。

/pukiwiki/image/counter
/pukiwki/lib/_db_counter.php
/pukiwiki/skin/pukiwki.skin.php
の3つをアップロードします。

* 設置見本 [#y7896f76]
アクセスカウンターを設置すると、メニューバーの下部に以下のようなカウンターが表示されます。

&ref(pukiwiki_db_counter.png);

*ソースコード [#j56c6894]

#code(php){{
<?php
// @date	2008/12/14
// @charactor	UTF-8N
// @description	MySQLを使ったpukiwiki用のアクセスカウンター PHP+MySQL

/*
### MySQL table ###

[pukiwiki_page] pukiwikiのページ名(文字列)をページID(数値)に変換して利用
id		INT		auto_increment
page		TEXT

[pukiwiki_access] アクセスログのテーブル ページID、IPアドレスを保存
id		INT		auto_increment
page_id		INT		index
ip		VARCHAR(32)
date		date		index
time		time
*/

//-----------------------------------------------
// config
//-----------------------------------------------

// DB
define('DB_USER',	'mysql_username');
define('DB_PASS',	'mysql_password');
define('DB_HOST',	'localhost');
define('DB_NAME',	'mysql_dbname');
define('DB_CHAR',	'UTF-8');
define('TBL_PAGE',	'pukiwiki_page');
define('TBL_ACCESS',	'pukiwiki_access');

// URL
define('DOMAIN',	'www.mydomain.com');
define('SCRIPT',	'/pukiwiki/index.php');

// ranking
define('TERM',	10);	// 集計期間(日)
define('NUM',	10);	// 順位数(例:10位までなら10)

//-----------------------------------------------
//接頭辞「a_」=「access」の意
$cmd    = $_GET['cmd']; // pukiwikiの処理モード
$a_page = mb_convert_encoding($_GET['page'], DB_CHAR); // pukiwikiページ名
$a_addr = $_SERVER["REMOTE_ADDR"]; // IPアドレス
$a_date = date('Y-m-d');
$a_time = date('H:i:s');

if (0 < strlen($a_page) && $cmd = 'read') {
	$conn = db_open(DB_USER, DB_PASS, DB_HOST, DB_NAME);
	
	//ページ名をページIDに変換
	$page_id = db_get_page_id($conn, $a_page);
	
	//wiki_accessに追加
	db_set_access($conn, $page_id, $a_addr, $a_date, $a_time);
	
	//カウンター値の取得
	$cnt_total     = db_get_total($conn);
	$cnt_page      = db_get_page($conn, $page_id);
	$cnt_today     = db_get_today($conn, $page_id, $a_date);
	$cnt_yesterday = db_get_yesterday($conn, $page_id, $a_date);
	
	//-----------------------------------------------
	//ランキング表示
	//-----------------------------------------------
	$date_to   = $a_date;
	$date_from = date_from($date_to, TERM);
	
	$rank = db_get_rank($conn, $a_date, TERM, NUM);
	if (0 < count($rank)) {
		echo "<h5>人気の".NUM."件</h5>\n";
		
		//集計期間
		echo "<div align='right'><span class='counter'>
			(".$date_from." - ".$date_to." / ".TERM."days)</span></div><br>\n";
		
		echo "<div>\n";
		echo "<ul>\n";
		foreach($rank as $page_id => $cnt) {
			$page_name = db_get_page_name($conn, $page_id);
			echo "<li><a href='http://".DOMAIN.SCRIPT."?".rawurlencode($page_name)."'>"
				.$page_name."<span class='counter'>(".$cnt.")</span></a></li>\n";
		}
		echo "</ul>\n";
		echo "</div>\n";
		echo "<hr>\n";
	}
	
	//-----------------------------------------------
	//カウンターの表示
	//-----------------------------------------------
	
	//-----------------------------------------------
	//テキスト 横長表示
	//-----------------------------------------------
	/*
	echo "<div align='right'>";
	echo "WIKI : "      . $cnt_total . " - ";
	echo "PAGE : "      . $cnt_page  . " - ";
	echo "TODAY : "     . $cnt_today . " - ";
	echo "YESTERDAY : " . $cnt_yesterday;
	echo "</div>";
	*/
	
	//-----------------------------------------------
	//テキスト 縦長表示
	//-----------------------------------------------
	/*
	echo "WIKI : "      . $cnt_total     . "<br>";
	echo "PAGE : "      . $cnt_page      . "<br>";
	echo "TODAY : "     . $cnt_today     . "<br>";
	echo "YESTERDAY : " . $cnt_yesterday . "<br>";
	*/
	
	//-----------------------------------------------
	//画像 縦長表示
	//-----------------------------------------------
	$digit         = strlen($cnt_total); // 桁数
	$cnt_page      = zero_add($cnt_page, $digit);
	$cnt_today     = zero_add($cnt_today, $digit);
	$cnt_yesterday = zero_add($cnt_yesterday, $digit);
	
	echo "\n<!--access counter-->\n";
	echo "<table border=0 cellpadding=0 cellspacing=0>\n";
	echo "<tr> <td align='left'><img src='image/counter/wiki.png'></td>
		<td align='right'>".rep_num($cnt_total)."</td> </tr>\n";
	echo "<tr> <td align='left'><img src='image/counter/page.png'></td>
		<td align='right'>".rep_num($cnt_page)."</td> </tr>\n";
	echo "<tr> <td align='left'><img src='image/counter/today.png'></td>
		<td align='right'>".rep_num($cnt_today)."</td> </tr>\n";
	echo "<tr> <td align='left'><img src='image/counter/yesterday.png'></td>
		<td align='right'>".rep_num($cnt_yesterday)."</td> </tr>\n";
	echo "</table>\n";
	echo "\n<!--access counter-->\n";
	
	db_close($conn);
}

//-----------------------------------------------
// function
//-----------------------------------------------

function db_open($mysql_user = '', $mysql_pass = '', $mysql_host = '', $mysql_db = '')
{
	$conn = mysql_pconnect($mysql_host, $mysql_user, $mysql_pass);
	mysql_select_db($mysql_db, $conn);
	return $conn;
}

function db_close($conn)
{
	return mysql_close($conn);
}

//MySQLプリペアードステートメント関数(SQLインジェクション対策)
//(参考)http://www.php.net/manual/ja/function.mysql-query.php#70686
function mysql_prepare($query, $phs = array()) {
	$phs = array_map(create_function('$ph', 'return "\'".mysql_real_escape_string($ph)."\'";'), $phs);
	$curpos = 0;
	$curph = count($phs)-1;
	for ($i = strlen($query) - 1; $i > 0; $i--) {
		if ($query[$i] !== '?') {
			continue;
		}
		if ($curph < 0 || !isset($phs[$curph])) {
			$query = substr_replace($query, 'NULL', $i, 1);
		} else {
			$query = substr_replace($query, $phs[$curph], $i, 1);
		}
		$curph--;
	}
	unset($curpos, $curph, $phs);
	return $query;
}

//ページ名をページIDにひも付け
function db_get_page_id($conn, $a_page = '')
{
	$page_id = 0;
	if (0 < strlen($a_page)){
		//既存値のdb検索
		$sql = "SELECT id FROM ".TBL_PAGE." WHERE page = ? LIMIT 1";
		$param = array($a_page);
		$query = mysql_prepare($sql, $param);
		$rst = mysql_query($query);
		if ($rst) {
			//page_idがあれば返す
			$row = mysql_fetch_row($rst);
			if (0 < count($row)) {
				$page_id = $row[0];
			}
		}
		
		//page_idがなければ、新規追加してpage_idを返す
		if ($page_id == 0) {
			$sql = "INSERT INTO ".TBL_PAGE." (page) VALUES (?)";
			$param = array($a_page);
			$query = mysql_prepare($sql, $param);
			mysql_query($query);
			$page_id = mysql_insert_id();
		}
	}
	return $page_id;
}

//ページIDからページ名を取得
function db_get_page_name($conn, $page_id = '')
{
	$page_name = '';
	if (0 < $page_id){
		//既存値のdb検索
		$sql = "SELECT page FROM ".TBL_PAGE." WHERE id = ? LIMIT 1";
		$param = array($page_id);
		$query = mysql_prepare($sql, $param);
		$rst = mysql_query($query);
		if ($rst) {
			//page_idがあれば返す
			$row = mysql_fetch_row($rst);
			if (0 < count($row)) {
				$page_name = $row[0];
			}
		}
	}
	return $page_name;
}

//アクセスログの記録
function db_set_access($conn, $page_id, $a_addr, $a_date, $a_time)
{
	// ToDo: INSERT IGNORE INTO に置き換える
	
	//重複チェック
	$cnt = 0;
	$sql = "SELECT count(*) FROM ".TBL_ACCESS." WHERE page_id = ? AND ip = ? AND date = ?";
	$param = array($page_id, $a_addr, $a_date);
	$query = mysql_prepare($sql, $param);
	$rst = mysql_query($query);
	if ($rst) {
		$row = mysql_fetch_row($rst);
		if (0 < count($row)) {
			$cnt = $row[0];
		}
	}
	
	//新規追加
	if ($cnt == 0) {
		$sql = "INSERT INTO ".TBL_ACCESS." (page_id, ip, date, time) VALUES (?, ?, ?, ?)";
		$param = array($page_id, $a_addr, $a_date, $a_time);
		$query = mysql_prepare($sql, $param);
		mysql_query($query);
	}
}

//全体のアクセス数
function db_get_total($conn)
{
	$cnt = 0;
	$sql = "SELECT count(*) FROM ".TBL_ACCESS;
	$rst = mysql_query($sql);
	if ($rst) {
		$row = mysql_fetch_row($rst);
		if (0 < count($row)) {
			$cnt = $row[0];
		}
	}
	return $cnt;
}

//ページのアクセス数
function db_get_page($conn, $page_id)
{
	$cnt = 0;
	$sql = "SELECT count(*) FROM ".TBL_ACCESS." WHERE page_id = ?";
	$param = array($page_id);
	$query = mysql_prepare($sql, $param);
	$rst = mysql_query($query);
	if ($rst) {
		$row = mysql_fetch_row($rst);
		if (0 < count($row)) {
			$cnt = $row[0];
		}
	}
	return $cnt;
}

//ページの本日のアクセス数
function db_get_today($conn, $page_id, $a_date)
{
	$cnt = 0;
	$sql = "SELECT count(*) FROM ".TBL_ACCESS." WHERE page_id = ? AND date = ?";
	$param = array($page_id, $a_date);
	$query = mysql_prepare($sql, $param);
	$rst = mysql_query($query);
	if ($rst) {
		$row = mysql_fetch_row($rst);
		if (0 < count($row)) {
			$cnt = $row[0];
		}
	}
	return $cnt;
}

//ページの昨日のアクセス数
function db_get_yesterday($conn, $page_id, $a_date)
{
	$yesterday = date('Y-m-d', (strtotime($a_date) - (1 * 24 * 60 * 60)));
	$cnt = 0;
	$sql = "SELECT count(*) FROM ".TBL_ACCESS." WHERE page_id = ? AND date = ?";
	$param = array($page_id, $yesterday);
	$query = mysql_prepare($sql, $param);
	$rst = mysql_query($query);
	if ($rst) {
		$row = mysql_fetch_row($rst);
		if (0 < count($row)) {
			$cnt = $row[0];
		}
	}
	return $cnt;
}

//カウンター用数字画像の表示
function rep_num($num)
{
	$str = '';
	for($i = 0; $i < strlen($num); $i++)
	{
		$num_i = substr($num, $i, 1);
		$str = $str . "<img src='image/counter/" . $num_i . ".png'>";
	}
	return $str;
}

//ゼロ詰め処理
function zero_add($num, $digit)
{
	$format = '%0'.$digit.'d'; // 「%04d」=4桁の整数
	$str = sprintf($format, $num);
	return $str;
}

//アクセスランキングのデータ取得
function db_get_rank($conn, $a_date = '', $term = '', $num = 1)
{
	$rank = array();
	
	//集計開始日の指定 $a_date がある場合
	if ($a_date) {
		$date_from = $a_date;
		$date_to = $a_date;
	}
	//集計開始日の指定 $a_date がない場合
	else {
		$date_from = date('Y-m-d');
		$date_to = date('Y-m-d');
	}
	
	//集計期間の指定がある場合
	if (0 < (int) $term) {
		$date_from = date_from($date_to, $term);
	}
	
	$rank = array();
	$sql = "SELECT page_id, count(*) AS cnt  FROM ".TBL_ACCESS
		." WHERE ? <= date AND date <= ? GROUP BY page_id ORDER BY cnt DESC LIMIT ".$num;
	$param = array($date_from, $date_to);
	$query = mysql_prepare($sql, $param);
	$rst = mysql_query($query);
	if ($rst) {
		while ($row = mysql_fetch_assoc($rst)) {
			$page_id = $row["page_id"];
			$cnt     = $row["cnt"];
			$rank[$page_id] = $cnt;
		}
	}
	return $rank;
}

//ランキング集計開始日の取得
function date_from($date, $term)
{
	$date_from = date('Y-m-d', (strtotime($date) - ((1 * 24 * 60 * 60) * (int) ($term - 1))));
	return $date_from;
}
?>
}}

*改造 [#icc3681f]
表示部分の画像や位置を、お好みに応じて変えてみてご利用ください。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS