(2023年4月15日)関数名変更,解説を増補した
サンプル・プログラム
counter.php | サンプル・プログラム本体。 |
バージョン | 更新日 | 内容 |
---|---|---|
3.3.0 | 2023/06/11 | ファイルオープン・エラー時のリトライ処理を追加 |
3.2.0 | 2021/03/06 | 関数名変更など |
3.1 | 2021/03/06 | PHP8対応 |
3.0 | 2015/05/19 | 大幅改訂 |
2.2 | 2008/08/20 | カウンタ・ファイルがない場合の初期化処理を追加 |
サンプル・プログラムの解説:準備
10: // 初期化処理 ================================================================
11: define('INTERNAL_ENCODING', 'UTF-8');
12: mb_internal_encoding(INTERNAL_ENCODING);
13: mb_regex_encoding(INTERNAL_ENCODING);
14: define('REFERENCE', 'https://www.pahoo.org/e-soul/webtech/php02/php02-04-01.shtm');
15:
16: //プログラム・タイトル
17: define('TITLE', 'PHPでアクセスカウンタを作る');
18:
19: //表示幅(ピクセル)
20: define('WIDTH', 600);
21:
22: //エラー時のリトライ回数
23: define('RETRY', 5);
24:
25: //カウンタを記録するファイル名;write enable属性を与えておくこと
26: $CounterFile = './mycounter.txt';
27:
28: /**
29: * 共通HTMLヘッダ
30: * @global string $HtmlHeader
31: */
32: $encode = INTERNAL_ENCODING;
33: $title = TITLE;
34: $width = WIDTH;
35: $HtmlHeader =<<< EOT
36: <!DOCTYPE html>
37: <html lang="ja">
38: <head>
39: <meta charset="{$encode}" />
40: <title>{$title}</title>
41: <meta name="author" content="studio pahoo">
42: <meta name="copyright" content="studio pahoo">
43: <meta name="ROBOTS" content="NOINDEX,NOFOLLOW">
44: <meta http-equiv="pragma" content="no-cache">
45: <meta http-equiv="cache-control" content="no-cache">
46: <meta http-equiv="X-UA-Compatible" content="IE=edge">
47: <meta name="viewport" content="width={$width},user-scalable=yes">
48: </head>
49:
50: EOT;
51:
52: /**
53: * 共通HTMLフッタ
54: * @global string $HtmlFooter
55: */
56: $HtmlFooter =<<< EOT
57: </html>
58:
59: EOT;
60:
61: // サブルーチン ==============================================================
このように、プログラムが終了してもデータを残したい場合は、ファイルやデータベースに書き込む。
ソースコードは UTF-8 で記述しているので、念のため、組み込み関数 mb_internal_encoding を使って宣言しておく。
プログラム・タイトルは定数 TITLE に、本ページのURLは定数 REFERENCE に定義しておく。これらは画面表示で参照する。
HTMLヘッダは変数 $HtmlHeader に用意しておく。
二重引用符による文字列記述は面倒なので、、ヒアドキュメントを利用する。
また、ページのキャッシングが行われてしまうとカウンタが増加したのが表示されないので、meta タグにキャッシング禁止指示 no-cache を指定している。
解説:カウンタを1つ加算する
62: /**
63: * カウンタを1つ加算する.
64: * @param string $fname カウンタ・ファイル名
65: * @return int カウンタ値
66: */
67: function addCounter($fname) {
68: //カウンタ・ファイルがあるかどうか調べ、無ければ作成する.
69: if (! file_exists($fname)) {
70: $fp = @fopen($fname, 'w');
71: fputs($fp, '0');
72: fclose($fp);
73: chmod($fname, 0644);
74: }
75:
76: //カウンター・ファイルをオープンする(リトライ付)
77: for ($i = 0; $i < RETRY; $i++) {
78: $fp = @fopen($fname, 'r');
79: if ($fp != NULL) break;
80: }
81: //直前のカウンタ値をカウンタ変数に読み込む.
82: $counter = (int)fgets($fp);
83: fclose($fp);
84:
85: //カウンタ変数を+1だけ増加させる.
86: $counter++;
87:
88: //カウンター・ファイルをオープンする(リトライ付)
89: for ($i = 0; $i < RETRY; $i++) {
90: $fp = @fopen($fname, 'w');
91: if ($fp != NULL) break;
92: }
93: //カウンタ変数をカウンタ・ファイルに書き込む.
94: flock($fp, LOCK_EX); //ロックをかける(排他制御)
95: $s = sprintf('%d', $counter);
96: fputs($fp, $s);
97: flock($fp, LOCK_UN); //ロックを解除する(排他制御)
98: fclose($fp);
99:
100: return $counter;
101: }
初めてこのプログラムを走らせるときには、カウンタ・ファイル $CounterFile は存在しない。
PHPスクリプトは、自分自身が初めて起動されたかどうかを知ることはできないので、関数 file_exists を使い、$CounterFile が存在しているかどうか検査する。
存在していなければ、初期値 0 を代入したファイルを生成し、関数 chmod によって所有者に書き込み権限を与える。
ファイルの内容を直接書き換えることは出来ない。
そこで、組み込み関数 fgets を使ってカウンタ・ファイル $CounterFile の内容を変数 $counter に読み込む。このとき、読み込んだ内容が整数であることを明示的に示す(キャスティング)するために (int) と書く。
次に、変数 $counter をインクリメント(+1加算)し、組み込み関数 fputs を使ってカウンタ・ファイル $CounterFile の内容を書き換える。
Webサービスでは、同時に複数のユーザーがサイトを閲覧することが有り得る。このとき、本プログラムも同時に複数が立ち上がる。一方、カウンタ・ファイル $CounterFile は1つしかない。
また、排他処理が働いているとき、他のスレッドが fopen してくる可能性があるので、定数 RETRY だけ繰り返してオープンするようにした(リトライ処理)。
そこで、書き換えている最中(レジで処理している最中)は、関数 flock によって、他のプログラムがファイルを書き換えないようロックする。
解説:アクセス回数の表示
103: /**
104: * HTML BODYを作成する.
105: * @param int $counter カウンタ
106: * @return string HTML BODY
107: */
108: function makeCommonBody($counter) {
109: $refere = REFERENCE;
110: $width = WIDTH;
111: $title = TITLE;
112: $version = '<span style="font-size:small;">' . date('Y/m/d版', filemtime(__FILE__)) . '</span>';
113:
114: $body =<<< EOT
115: <body>
116: <h2>{$title} {$version}</h2>
117: <p>
118: あなたは {$counter} 人目の訪問者です
119: </p>
120: <div style="border-style:solid; border-width:1px; margin:20px 0px 0px 0px; padding:5px; width:{$width}px; font-size:small; overflow-wrap:break-word; word-break:break-all;">
121: ※参考サイト:<a href="{$refere}">{$refere}</a>
122: </div>
123: </body>
124:
125: EOT;
126: return $body;
127: }
ここでは、最も基本的なカウンタ・プログラムの作り方を紹介する。