※このサンプルの解説は、「CGI(Perl)の解説」をすべて読み終えてる方を前提としています。
■ グラフィックカウンタの作成(CGI形式)
さて、今回はちょっと厄介なCGI形式のグラフィック型のアクセスカウンタです。
CGI形式は何故厄介かというと、画像を直接出力しないといけないからです。
CGI形式では、その呼び出しは直接タグ内に記述されないといけませんから、可能なタグとすれば「img」タグぐらいしかありません。
しかも、固定的な画像なら問題はないのですが、カウンタはそのたび画像の内容が変わります。
これをCGIで組み合わせながら出力しないといけないからです。
本来ならその桁数文の画像を結合させ1つの画像として出力するのが一番いいのですが、そうなると画像の結合処理も作らないといけなくなります。
この結合処理がまたかなり厄介で簡単なサンプルでは作れません。
したがって今回は、1桁ずつ表示する方法を取って、画像の結合処理を必要としないようにします。
※..もし、画像結合の方法を取りたい場合は、「とほほ」さんの「CGIソフト集」に「GIF画像連結ライブラリ」というのがあるので試してみるのもいいでしょう。
それと、グラフィックカウンタということなので当然画像が必要になります。
画像は、数字の「0」~「9」に対応した画像
、「0.gif」~「9.gif」が用意されているとします。
これらの画像についてはこのサイトの「フリー素材」にある「アクセスカウンタ」関係から入手すれば簡単でいいでしょう。
- 【 解 説 】
-
さて、まず最初に、カウンタの中から任意の桁の数字を取得するにはどうすればいいのでしょうか?
そのヒントは以前解説した「グラフィックカウンタの作成(SSI形式)」の中にあります。
そうですね、「substr()」関数を使用すれば可能です。
カウンタの値が「$totalc」にセットされていて、取得したい桁が「$ketai」にセットされていた場合、次のように記述すれば取得できます。
$suji = substr($totalc, $ketai-1, 1);そして、これに該当する画像は「$suji.gif」というファイル名になりますから、この画像を出力する処理はファイルの読込処理を使い次のように記述します。
$filnam = "$suji.gif"; open(FP, $filnam); read(FP, $gdat, 10000); close(FP); print $gdat;では、最初の「指定した桁」はどのようにしたらいいのでしょうか?
これは、このCGIの呼び出しの時、「指定した桁」をパラメータとして与えます。
このCGIを「gcntc.cgi」とした時、1桁目を呼び出す場合は次のような感じです。
gcntc.cgi?1そして、これを取得するには「CGI(Perl)の解説」で解説したとおり次のように記述できます。
$ketai = @ARGV[0];さらに、もう少し手を加えましょう。
このままでは、カウンタの桁数が1桁から2桁へ、2桁から3桁へと増えていった時にたびたび記述を追加しなくてはならなくなります。この時の対応として、2通りの方法が考えられます。
ひとつはカウンタを固定桁数にしてしまう方法で、もうひとつは桁数あふれの場合の処理を追加する方法です。
今回は難しい後者の方法を取ってみます。現在のカウンタの桁数は以前の「グラフィックカウンタの作成(SSI形式)」で解説しました。
表示したい桁がこの桁より大きい場合は「何も表示しない画像」を表示します。
この時、本当に何も表示しなければと表示されてしまうのでまずいわけですね。そこで、このサイトの「フリー素材」にある「アクセスカウンタ」関係の画像の中に「no.gif」という画像があると思います。
この画像が「何も表示しない画像」です。したがって、この切り分けは「if」文を使い、それぞれカウンタのファイル名を指定します。
その方法は次のように、カウンタ以下の桁数なら指定したファイル名を、それ以外なら「何も表示しない画像」のファイル名にします。
if ($ketai <= $ketat){ $filnam = "$suji.gif"; }else{ $filnam = "no.gif"; }まだ問題があります。
このCGIカウンタの場合、各桁ごとにこのCGIを呼び出すわけですから、6桁カウンタなら全部で6回呼ばれ、このままではカウンタが6ずつアップすることになります。そこで、カウントアップ用の処理と画像表示用の処理も切り分けないといけないということになります。
パラメータに「0」を与えた時、カウントアップ処理を行うように「if」文で切り分けしましょう。
その「if」文は次の通りです。
if ($ketai == 0){ }else{ }今回、カウンタのファイル名は「gcntcf.cgi」としました。
このファイル名は何でもいいのですが、セキュリティの意味で拡張子は「.cgi」
にしておくことをお勧めします。このようにしておくと、訪問者がこのファイルを覗こうとした時、自動的にCGIとして実行しようとしますが、中身がCGIではないのでエラーが発生します。
したがって、覗こうとしてもエラーが発生して覗けなくなるからです。
まずこのカウンタを呼び出すためのHTMLページを「gcntc.html」という名前で作成します。
カウンタの桁数を6桁にした時のサンプルは次の通りです。
- 【記述サンプル】
-
<HTML>
<HEAD>
<title>CGI形式のグラフィック型カウンタ</title>
</HEAD>
<BODY>
<img src="./gcntc.cgi?0"><img src="./gcntc.cgi?1"><img src="./gcntc.cgi?2"><img src="./gcntc.cgi?3"><img src="./gcntc.cgi?4"><img src="./gcntc.cgi?5"><img src="./gcntc.cgi?6">
</BODY>
</HTML>
そして、上記の内容を使用して「CGI形式のグラフィック型カウンタ」を作成します。
この時注意点がひとつあります。
画像データとして出力する場合、下記サンプル3行目のように「print "Content-type:text/html\n\n";」 を追記しないと正常に動作しないサーバーがあります。
なお、今回のサンプルでは排他制御(同時書き込み時の制御)は行っていません。
Windows環境の排他制御については「CGI(Perl)の予備知識」-「ファイル書き込みの排他制御」をご参照下さい。
- 【記述サンプル】
- #!/usr/bin/perl print "Content-type:text/html\n\n"; $ketai = @ARGV[0]; $filnam = "gcntcf.cgi"; open(FP,"<$filnam"); $totalc = <FP>; close(FP); if ($ketai == 0){ $totalc++; $filnam = "gcntcf.cgi"; open(FP,">$filnam"); print FP "$totalc"; close(FP); $filnam = "no.gif"; }else{ $ketat = length($totalc); $suji = substr($totalc, $ketai-1, 1); if ($ketai <= $ketat){ $filnam = "$suji.gif"; }else{ $filnam = "no.gif"; } } open(FP, $filnam); read(FP, $gdat, 10000); close(FP); print $gdat;