本記事の内容
- PHPで簡素なアクセスカウンターを作る
- html内からCGIとして実行
背景
以前Hugoで黒歴史サイトを作成した.
その際,アクセスカウンターとしてnpc.cgiを使ったのだが
- 明らかに古そう
- 画像で表示される
といった問題が有り,常々なんとかしたいと思っていた.
がんばって勉強した結果,CGI機能を使えばHTMLファイル内から自由にプログラムを実行できることを知り,勉強がてらアクセスカウンターを作ろうとした次第である.
なんでPHP?
サーバーのコマンドを自由に実行できるならPythonやRubyでも良いじゃんと思われるかもしれない.
ていうか自分もそう思っていた.しかし,さくらのレンタルサーバーだと
- Pythonが2.7しか無い
- Rubyのバージョンもメンテナンス終了ギリギリ
という環境なので断念した.一方でPHPは最新のものが入っていたため,PHPでアクセスカウンターを作ることにした.
結果
作ったもの
長々と中身のない話をしてもしょうがないので早速制作物を示す.
#!/usr/local/bin/php
<?php
header('Content-type: text/html; charset=utf-8');
$lock = './counter.lock';
$counter = './counter.json';
if (!$lockfile = fopen($lock, "a")) {
die("ロックファイルが開けません");
}
flock($lockfile, LOCK_EX);
if(!file_exists($counter)){
die("カウンターが開けません");
}
$json = file_get_contents($counter);
$json = mb_convert_encoding($json, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');
$arr = json_decode($json,true);
$num = $arr["counter"];
echo $num;
$arr["counter"] = $num + 1;
if (!$counterfile = fopen($counter, "w")) {
die("カウンターが開けません");
}
fwrite($counterfile, json_encode($arr));
fclose($counterfile);
flock($lockfile, LOCK_UN);
fclose($lockfile);
?>
これをcgiファイルとして保存する.
次に同じディレクトリにcounter.lock(空ファイルでいい)と
counter.json({ "counter" : 0})を作る.
ポイント
ロックファイルを使い競合を防ぐ
私のサイトは1日10人も見ないような(多分アクセスしてるのもbot)サイトだが,
万が一同時に複数人がアクセスするとファイルが破損する恐れがある.
そのため,lockファイルを作り,同時に1プロセスずつしか実行できないようにした.
JSONでデータを管理
アクセス数を保存するだけなのにJSONを使うのは仰々しいが,ややこしい処理をしなくても
簡単にファイル内の変数にアクセス,編集できるためJSONファイルにアクセス数を保存した.
HTMLファイルから呼び出す
HTMLファイルからCGIファイルを呼び出す方法はいくつか有るが,ここではSSI機能を使った.
SSIとはServer Side Includesの略で,所定の形式でコメントを挿入すると,サーバーが適宜
コマンドの実行結果に置き換えてくれる機能である.
今回は以下の形で挿入した.
<!--#include virtual="/hoge/counter/counter.cgi"-->
## 注意点
さくらのレンタルサーバーでSSI機能を使うには,CGIを呼び出すhtmlファイルの拡張子をshtmlにする必要がある.