2011/02/19

魔法使いの弟子(その8-3) ~PHPに挑む~

【ミッション: PHP でアクセスカウンタを作れ】

前々回のあらすじ: XAMPP 入り USB メモリを作ってみた。
前回のあらすじ: MySQL をてきとうに動かしてみた。

いよいよ PHP に手を出すときがきた。

とはいってもぼくは初心者だし、簡単なところから始めようと思う。

文字列を出力する手段である echo の存在を知ったぼくは、まず以下の HTML ファイルを作ってみた。
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">  
  2. <html lang="ja">  
  3.     <head>  
  4.         <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
  5.         <title>たーせるのホームページ</title>  
  6.     </head>  
  7.   
  8.     <body>  
  9.         <p><?php echo 'おまえは、もう、氏んでいる'; ?></p>  
  10.     </body>  
  11. </html>  
うまく行けば、北斗の拳(アニメ版)の有名なセリフが表示されるはずだが……。

ファイル名は baka.html である。 baka って…。

あるぇー。何も表示されてない。どうしようどうしよう。



そうか、デフォルトでは HTML ファイルに埋め込まれた PHP スクリプトを実行できないのか。

……やむを得ない。少々面倒だが設定を変えよう。 HTML ファイルがあるフォルダに .htaccess ファイルを作り、そこに
  1. AddType application/x-httpd-php .htm .html  
と書く事にする。

さっそくテキストファイルを新規作成して、名前を .htaccess に変更して……
……って、なんかエラーでた

そうだった。『.htaccess』のようなピリオドから始まるファイルは Windows 環境では作れない。ぼくは Windows っ子であるにもかかわらず、こういう事は Unix 環境でしかやった事がないので、Windows のこの仕様をすっかり失念していた。

Unix 系 OS が導入された Web サーバならば、暫定的に『htaccess.txt』みたいなファイル名を付けて、アップロード後にリネームする事ができる。

しかし、今はテストサーバを Windows 環境上に構築しているため、こういった裏技的芸当は使えないのだ。

しょうがないので、 x:\XAMPP\httpd.conf に以下を追加した。これで、『.htaccess』の代わりに、『htaccess.txt』を使う事ができるようになる。
  1. AccessFileName htaccess.txt  
  2.   
  3. <Files htaccess.txt>  
  4. Order allow,deny  
  5. Deny from all  
  6. </Files>   
念のため、Apache を再起動。

その後、再度 htaccess.txt を作り、テキストエディタで
  1. AddType application/x-httpd-php .htm .html  
と書いた。

よし、ブラウザのリロードだ。


やった。できた。



いよいよ、アクセスカウンタを作ってみる。

カウンタの値は、外部ファイル counter.dat に保存する事にした。

まずは初期値として、「0」とだけ書いた counter.dat ファイルを新規作成。


作った DAT ファイルは必ず閉じておこう

一方、カウンタを実現する PHP のソースはこんな感じである。
  1. <?php  
  2.     $filename = 'counter.dat';  
  3.   
  4.     # counter.dat を開く  
  5.     $fp = fopen($filename"r+");  
  6.   
  7.     # ファイルから読み込み  
  8.     $count = fgets($fp);  
  9.   
  10.     # カウンターを1増やす  
  11.     $count++;  
  12.   
  13.     # ファイルに上書き  
  14.     fseek($fp, 0);  
  15.     fputs($fp$count);  
  16.   
  17.     # ファイルを閉じる  
  18.     fclose($fp);  
  19.   
  20.     # カウンターの値を表示  
  21.     echo $count;  
  22. ?>  

上記ソースを HTML ファイルに埋め込んでみる事にする。
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">  
  2. <html lang="ja">  
  3.     <head>  
  4.         <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
  5.         <title>たーせるのホームページ</title>  
  6.     </head>  
  7.   
  8.     <body>  
  9.         <h1>たーせるのホームページ</h1>  
  10.         <p>  
  11.             いらっしゃいませ!あなたは  
  12.             <?php  
  13.                 $filename = 'counter.dat';  
  14.                   
  15.                 # counter.dat を開く  
  16.                 $fp = fopen($filename, "r+");  
  17.                   
  18.                 # ファイルから読み込み  
  19.                 $count = fgets($fp);  
  20.                   
  21.                 # カウンターを1増やす  
  22.                 $count++;  
  23.                   
  24.                 # ファイルに上書き  
  25.                 fseek($fp, 0);  
  26.                 fputs($fp, $count);  
  27.                   
  28.                 # ファイルを閉じる  
  29.                 fclose($fp);  
  30.                   
  31.                 # カウンターの値を表示  
  32.                 echo $count;  
  33.             ?>  
  34.             人目のお客さんです!  
  35.         </p>  
  36.     </body>  
  37. </html>  

これを適当な名前で保存し、Web ブラウザで開くと……


計画通り……!! リロードすればするだけカウンターが上がっていく。すばらしい。

と見せかけて、これだけでは実用面において不十分なのである。

並列プログラミングにも言える事だが、カウンタ値を保持している couter.dat は閲覧者にとって共有資源であり、万一同時にアクセスされた場合にはうまくカウントされない。

本格的にやるならば、counter.dat をロックしたりアンロックしたりと排他制御を施さねばならない。この処理は大して難しくないので、厳密に実装したい場合は適当に調べてみるとよい。

ぼくは知らん。



それはそうと、アクセスカウンタは『ほら、ぼくのサイトはこんなに人気があるんですよ』アピールのためだけに存在すると思っている(偏見)。

その昔、虚栄心の塊だったぼくが Web サイトを開設したばかりの頃、ひたすらリロードを繰り返してはアクセスカウンタを水増ししていたものである(まさかのカミングアウト)。

今日は、そんな面倒なマネをしなくとも自動的にカウンタを水増ししてくれる素敵なプログラムを作ってお別れしよう。

諸悪の根源は、変数 $count を 1 しか増やしていないせいである。
  1. $count++;  
これを爆発的に増加させる事ができれば、アクセスカウンターなどコントロールし放題である。

とはいえアクセスするたびに数字が一律に増加するのも不自然なので、適当に乱数を発生させて、それを $count に足し込む事にする。

最小値 min と最大値 max を指定して乱数を発生する関数は
  1. int rand([int min, int max])  
らしいので、思い切って 1~1000000 の範囲で乱数を発生させてみよう。

先ほどのインクリメント処理を、
  1. $count += rand(1, 1000000);  
に書き換えて再びブラウザをリロードすると……。


このように卑怯くさいチートが完成した。

これでぼくも大人気サイトの仲間入りだ! やったね! むなしいけど。