PukiWiki

概要

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

インストール

以下の手順でインストールできます。

免責

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

ダウンロード

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

filepukiwiki_db_counter.zip

データベースのテーブル作成

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 ;
}}

設定の編集

解凍したフォルダ「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)
}}

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

設定項目内容
DB_USERMySQLを利用するユーザー名
DB_PASSMySQLを利用するパスワード
DB_HOSTMySQLのホスト名(通常は「localhost」)
DB_NAMEMySQLのデータベース名
DB_CHARMySQLの文字コード(通常は「UTF-8」)
TBL_PAGEpukiwikiのページ名を保存するテーブル名(通常は「pukiwiki_page」)
TBL_ACCESSpukiwikiのアクセスログを保存するテーブル名(通常は「pukiwiki_access」)
DOMAINpukiwikiが設置してあるWebサイトのドメイン名
SCRIPTpukiwikiのスクリプトまでのパス
TERMアクセスカウンターで表示する集計期間の日数
NUMアクセスカウンターで表示する順位数(例:上位10位までなら10)

アクセスカウンター

「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>
}}

ファイルの配置

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

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

設置見本

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

pukiwiki_db_counter.png

ソースコード

#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));
return $date_from;
}
?>
}}

改造

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


*1 1 * 24 * 60 * 60) * (int) ($term - 1

添付ファイル: filepukiwiki_db_counter.png 704件 [詳細] filepukiwiki_db_counter.zip 578件 [詳細]

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-03-27 (日) 19:04:42