※このサンプルの解説は、「CGI(Perl)の解説」をすべて読み終えてる方を前提としています。
後になるほど省略されている場合がありますのでできるだけ順番に読んでください。
また、実行に際しては、サーバーでPHPが利用できる事を前提に解説しています。
■ グラフィック型カウンタの作成(CGI形式)
さて、今回はちょっと厄介なCGI形式のグラフィック型のアクセスカウンタです。
厄介ではありますが、SSI形式と違い、画像形式ですから「img」タグで呼び出しができるので、ほとんどのサーバーで使用する事ができるというメリットがあります。
CGI形式は何故厄介かというと、画像を直接出力しないといけないからです。
CGI形式では、その呼び出しは直接タグ内に記述されないといけませんから、可能なタグとすれば「img」タグぐらいしかありません。
しかも、固定的な画像なら問題はないのですが、カウンタはそのたび画像の内容が変わります。
これをCGIで組み合わせながら出力しないといけないのです。
本来ならその桁数分の画像を結合させ、1つの画像として出力するのが一番いいのですが、そうなると画像の結合処理も作らないといけなくなります。
この結合処理がまたかなり厄介で、画像フォーマットの内部形式を理解しないと作成ができないので、簡単なサンプルでは作れません。
したがって今回は、1桁ずつ表示する方法を取って、画像の結合処理を必要としないようにします。
※..もし、画像結合の方法を取りたい場合は、「とほほ」さんの「CGIソフト集」に「GIF画像連結ライブラリ」というのがあるので試してみるのもいいでしょう。
それと、グラフィックカウンタということなので当然画像が必要になります。
画像は、数字の「0」〜「9」に対応した画像 、「0.gif」〜「9.gif」が用意されているとします。
これらの画像についてはこのサイトの「フリー素材」にある「アクセスカウンタ」関係から入手すれば簡単でいいでしょう。
- 【 解 説 】
-
さて、CGI形式のグラフィック型アクセスカウンタと言えど、基本は同じです。
要点は、どうやって指定した1文字を取得(表示)するかだと思います。まず呼び出し方法を決めておきましょう。
今回のPHPスクリプトの名前を「gcntc.php」とします。
そして呼び出したい桁位置をパラメータとして与えます。
例えば、2桁目を取得(表示)したい場合は、「gcntc.php?2」と呼び出すこととします。では、このパラメータをPHP側で取得するにはどのようにすればいいのでしょうか?
それは、PHPが標準で持っている環境変数「_SERVER["QUERY_STRING"]」から取得する事ができます。ですから、桁位置を「$ketas」という変数にセットする場合は、次のように記述します。
$ketas = $_SERVER["QUERY_STRING"];この「$ketas」を使用してカウンタの文字を「$cnt0」という変数にセットするには次のように記述します。
$cnt0 = substr($totalc, $ketas - 1, 1);この場合、「substr()」関数を使用した文字位置は「0」から開始しますので「$ketas - 1」と指定します。
これを使用して、該当する画像ファイルを読み込み、その画像データをそのまま出力します。
その方法はファイルの読込処理を使い次のように記述します。
$filnam = "$cnt0.gif"; $fp = fopen($filnam,"r"); $imgdat = fread($fp, filesize($filnam)); fclose($fp); print $imgdat;この例では、カウンタ用の画像はこのPHPスクリプトと同じフォルダに「0.gif」〜「9.gif」という名前で存在しているものとします。
これで、このPHPスクリプトを呼び出せば画像データと同じものが出力されることになります。
したがって、「img」タグでこのスクリプト名を記述すれば、画像ファイル名を記述するのと同じように普通に画像表示がされるようになります。
ただ、これだけではまだ不完全です。
なぜならこのスクリプトはそれぞれの桁ごとに呼び出されるため、このままでは一度の表示で複数回のカウントアップがなされてしまいます。そこで、画像の表示とカウントアップの処理を切り分けます。
パラメータが指定されてない場合のみカウントアップを行い、それ以外の場合は画像の表示のみを行うように切り分けます。
その処理は「if」文を使用して次のように記述できます。
if (empty($ketas)){ }else{ }この時、「$ketas」に何も入ってなければ、カウントアップ処理を行い、それ以外の場合は画像データを出力したいわけですから、この「if」文には次のように記述いたします。
if (empty($ketas)){ $totalc = trim($totalc); $totalc++; $filnam = "gcntcf.cgi"; $fp = fopen($filnam,"w"); fputs($fp,"$totalc"); fclose($fp); }else{ $cnt0 = substr($totalc, $ketas - 1, 1); $filnam = "$cnt0.gif"; $fp = fopen($filnam,"r"); $imgdat = fread($fp, filesize($filnam)); fclose($fp); print $imgdat; }まだ、不完全です。(^_^;)
このままでは、カウントアップのみの時、画像データを出力してませんから、「img」タグの表示が のようになってしまいます。
そこで、『何も表示しない画像』を表示させないといけません。そこで、このサイトの「フリー素材」にある「アクセスカウンタ」関係の画像の中に「no.gif」という画像があると思います。
この画像が『何も表示しない画像』です。これを利用して先ほどの「if」文を書き変えましょう。
次のような具合です。
if (empty($ketas)){ $totalc = trim($totalc); $totalc++; $filnam = "gcntcf.cgi"; $fp = fopen($filnam,"w"); fputs($fp,"$totalc"); fclose($fp); $cnt0 = "no"; }else{ $cnt0 = substr($totalc, $ketas - 1, 1); } $filnam = "$cnt0.gif"; $fp = fopen($filnam,"r"); $imgdat = fread($fp, filesize($filnam)); fclose($fp); print $imgdat;今回、カウンタのファイル名は「gcntcf.cgi」としました。
このファイル名は何でもいいのですが、セキュリティの意味で拡張子は「.cgi」
にしておくことをお勧めします。このようにしておくと、訪問者がこのファイルを覗こうとした時、自動的にCGIとして実行しようとしますが、中身がCGIではないのでエラーが発生します。
したがって、覗こうとしてもエラーが発生して覗けなくなるからです。
まずこのカウンタを呼び出すためのHTMLページを「gcntc.html」という名前で作成します。
カウンタの桁数を4桁にした時のサンプルは次の通りです。
- 【記述サンプル】
-
<HTML>
<HEAD>
<title>グラフィック型カウンタ(CGI形式)</title>
</HEAD>
<BODY>
累計のカウント:
<img src="./gcntc.php?0"><img src="./gcntc.php?1"><img src="./gcntc.php?2">
</BODY> </HTML>
そして、上記の内容を使用して「CGI形式のグラフィック型カウンタ」を作成します。
この時注意点がひとつあります。
画像データとして出力する場合、下記サンプル3行目のように「print "Content-type:text/html\n\n";」を追記しないと正常に動作しないサーバーがあります。
不要の場合もあります。
なお、今回のサンプルでは排他制御(同時書き込み時の制御)は行っていません。
Windows環境の排他制御については「PHPの予備知識」−「ファイル書き込みの排他制御」をご参照下さい。
- 【記述サンプル】
- <?php print "Content-type:text/html\n\n"; $ketas = $_SERVER["QUERY_STRING"]; $filnam = "gcntcf.cgi"; $fp = fopen($filnam,"r"); $totalc = fgets($fp); fclose($fp); if (empty($ketas)){ $totalc = trim($totalc); $totalc++; $filnam = "gcntcf.cgi"; $fp = fopen($filnam,"w"); fputs($fp,"$totalc"); fclose($fp); $cnt0 = "no"; }else{ $cnt0 = substr($totalc, $ketas - 1, 1); } $filnam = "$cnt0.gif"; $fp = fopen($filnam,"r"); $imgdat = fread($fp, filesize($filnam)); fclose($fp); print $imgdat; ?>