[ # 1 ]   A c c e s s   C o u n t e r
Top > Entrance > Tutorial > [#1] Access Counter

Flow Necessaries Source About How2Use

 

  ●● Introduction ●●●●●
先生 今回は「これぞCGI!」というべきスクリプト、基本ワザのいっぱい詰まってなおかつとても利用価値の高い「アクセスカウンタ」の解説だっ。
ミナ ほうほう。ホームページ持ってる人ならたいていお世話になってるアレですね。
先生 その通り。まあプロバイダが用意してるものとか、無料のカウンタとかもあるが、「自分で作ってみる」コトにイミがあるのだというふうに割り切っていこう。
ミナ 自分で画像を作ってカウンターにできるのはソレはソレで楽しいですもんねっ。
先生 オオめずらしく前向きコメントだッ。



  ●● Flow ●●●●●

【処理の流れとポイント】

カウント数の読み込み   [ open ]関数、ファイルの読み込み
   
カウントアップ、
カウント数記録
  ファイルへの書き込み
   
数字の分割   [ split ]関数
   
表示   [ foreach ]による繰り返し



  ●● Necessaries ●●●●●

【必要アイテム/パーミッション設定】

【ファイル名】 Permission 【働き】
count.cgi 755 ファイル読み込み〜カウントアップ〜出力
count.txt 666 カウント数を記録するテキストファイル
0.gif
|
9.gif
644(標準) カウンタ用画像ファイル10



  ●● Source ●●●●●


[ count.cgi ]

1 #!/usr/local/bin/perl
   
2 #カウント用ファイルの選択
3 $datafile="count.txt";
   
4 #カウントの読み込み
5 open ( DATA, "$datafile");
6 $number = <DATA>;
7 close ( DATA );
   
8 #カウントアップ
9 $number = $number+1;
   
10 #カウントの書き込み
11 open ( DATA, "> $datafile");
12 print DATA $number;
13 close ( DATA );
   
14 #数字の分割
15 @counter = split (//,$number);
   
16 #先頭に0をつける
17 while ( $#counter+1<6 ){
18 @counter = ( 0,@counter );}
   
19 #表示
20 print "Content-type: text/html¥n¥n";
21 foreach $key ( @counter ){
22 print "<img src=¥"images/$key.gif¥">";}

※行番号は便宜上表記しているだけです。 実際のスクリプトには行番号はつきません。



  ●● About this Script ●●●●●
ミナ ・・・うう〜ん・・・よくわかんないなあ・・・。
先生 前回と比べると確かに複雑なスクリプトになってる。しかしコレまた『ファイルハンドル』とか『配列』とか『文字列の分割』とか、めんどくさいが覚えなきゃならんワザがてんこ盛り。これらが使えるとけっこういろんなコトが出来るようになるぞ。
ミナ むむう。ちょっとくじけぎみ・・・。
先生 よっし気合いでイくぞっ。さて、3行目。[ $datafile ]という変数の中に[ count.txt ]を代入している。この変数はあとで頻繁に使うから、処理が楽なようにこうするんだ。また[ count.txt ]というファイルはこれまでにアクセスされた回数が記録してあるファイル。初期値は自由に設定すればよい。
ミナ 例えば100から始めたいなら、『100』て1行だけ書いたテキストファイルを作る、てコトですか?
先生 まさにその通り。サエてるぞミナくん。
さて、5行目には今回が初出の[ open ]という関数がある。これがこのスクリプト第1のポイントだ。

(文例) open YYY, "xxx";

といった書き方をするのであるが、[ xxx ]にはファイル名が入る。さっきので言えば[ $datafile ]だな(この変数に既に[ count.txt ]というファイル名が代入されているので)。
で、その前の大文字の[ YYY ]の部分は『ファイルハンドル』と呼ばれるモノだ。ま、ファイルの中身を入れておく容れモノ、ぐらいに考えておけばいい。とりあえず大文字で書いといたほうが良い。
で、関数全体では、[ xxx ]というファイルを開いて、その中身を[ YYY ]という容れモノに入れてください、というイミになる。
スクリプトのもので言えば[ $datafile ]を開いて中身を[ DATA ]という容れモノに入れる処理をしてるわけだ。
なんでこんなことをするかって言うと、外部のファイルを読み込んでイキナリ変数に代入する、というコトはいかにPerlでも出来ないんだ。 だからいったんファイルハンドルを使うというわけ。
ミナ じゃあ6行目がその[ DATA ]を変数[ $number ]に代入してる、てコト?
先生 いえっす! すごいぞミナくん。おとなになったものだ。
その後、[ open ]で開いたファイルハンドルは処理が終了したら閉じなきゃならんというのがルールだから、変数に代入したら(スクリプトがファイルの内容を扱えるように読み込みが終了したら)7行目の[ close ]でファイルハンドル[ DATA ]を閉じる。
ミナ 9行目はアクセス数のカウントアップですか?
先生 そうそう。これはそのまんまだな。ちなみにこの[ +1 ]の部分を5とか10とかにしてやれば、1回のアクセスでガツンと数字の増えるインチキカウンターも作れてしまうわけだ。逆に-1とかにすればカウントダウンになるし。・・・ははっ、そのうち面白カウンタ特集でも組もうかな。
ミナ 〜〜〜。・・・あれッ、11行目にまた[ open ]が出てきましたよ?
先生 ふむ。今度はさっきカウントアップした数字を、さっきの[ count.txt ]に書き込んでやらにゃならん。ファイル名の前に[ > ]を付けると、「書き込む目的のためにファイルを開いてちょうだい」というイミになる。なにも付けない状態(5行目)のは、単に「読み込むためにファイルを開く」ためのものだ。
12行目でファイルに新しい数を書き込んだ後、13行目で閉じる。ファイルに書き込むための命令は [ print ]。ここでは[ DATA ]の中に[ $number ]を書き込む、というイミになる。(ファイルハンドルにまた[ DATA ]を使っているが、別に前出のものとおんなじにしておく必要はない。単にラクだからこうしているだけだ。)
ミナ はう〜〜〜。もォ解んないからつぎつぎッ。「数字の分割」てのは?
先生 うむ。基本的に、文字列のまんま出力するなら、あと最後に[ print $number; ]とでも書き出してスクリプトを終了すりゃそれで良いのだ。でも、やっぱりカウンターには画像を使いたいだろ?
でも、 例えば10000までの数字を表示するのに、 10000コの画像ファイルを用意するのはアホのやることだ。
数字を分割すれば、[10000][1][0][0][0][0]というふうに分けられる。[935]なら[9][3][5][128470]なら[1][2][8][4][7][0]。つまり0から9までのたった10コの画像でどんな数字でも表示できる、て寸法さ。 わかるかい?
ミナ ・・・先生っすごいッ。なーるほど。
先生 感心するのは15行目の関数のしくみを聞いてからにしてくれ。ココではまた初出の関数[ split ]がある。第2のポイントだ。

(文例) split ( // , $string );

という書き方になる。イミとしては、[ $string ]内の文字列を1文字ずつ分割してください。というコト。
ダブルスラッシュ(//)のあいだに特定の文字(記号)を指定したり『正規表現』でメタ文字を入れたりなどでいろいろなパターンで分割できるが、とりあえず『ダブルスラッシュ=1文字ずつ分割』と覚えておけばよい。
ミナ うう。わからなすぎ。メタ?
先生 まあそんな悩むことはない。必要になったら覚えよう。私もよく解らんし。
で、分割した数字を変数に代入するんだが、ここでは『配列』というしくみを使う。 ただの変数を[ $ ]つきの文字列で表したのに対し、配列には[ @ ]がつく。・・・まあ、変数を格納しておくフォルダみたいなもん、と考えると解りやすいか。
さて16行目から18行目では、アクセス数が1000006桁)以下の場合、数字の前に[0]を付けるよ、という処理をしているのだが、ココはこのスクリプトの中ではもっとも高度な理解が要求されるところなので、今はやめておく。もっとperlのことがわかるようになってから、どういうイミなのか自分で調べるといい。
ミナ はぁ・・・ココまででも充分高度だよ・・・。
先生 さ、もうちょっとだっ。幸運にも最後のポイント[ foreach ]による繰り返しはそんなに難しくない。

(文例) foreach $string (@list ) { ... };

これは、 配列[ @list ]内の要素(という言い方をする。個々の数値なり文字列なりのこと)を [ $string ]に代入したあと、{ }内の処理を実行し、[ @list ]の要素全てに関して処理が終わったら終了する、というモノだ。
実例では、[ @counter ]内の要素を[ $key ]という変数に代入し、{ }内でブラウザ側に出力する、というのを要素の数だけ(つまり6桁分)繰り返す、という処理になってる。
ミナ やっと終わったぁ・・・。
先生 お疲れさん。最初のスクリプトと比べると随分難しくなってるが、はじめも言ったようにこれがカンペキに理解できたならPerlの基本は押さえられたと言っていいと思うね。説明が早足だが、関連書籍なんかを見ながらじっくり取り組むと案外すんなりイくはず。




  ●● How 2 Use ●●●●●
先生 スクリプトができ上がったが、実際これをどう使うか、という説明がまだだったな。
ミナ え? まだなんかあるんですか?
先生 そもそもCGIていうものはホームページを見ている人が何らかのアクションを起こして初めて働くものだ。フォームのボタンを押すとかな。
けど実際、『カウンターを表示するためにこのボタンを押して』なんてカッコ悪くてホームページには書けんだろ。
だから、そのページ(HTMLファイル)が読み込まれるのと同時にスクリプトを起動しなきゃイカン。
ミナ どうやるんですか? スクリプトを起動するタグを使うとか? <cgi src="***.cgi">みたいな?
先生 そんな珍妙なタグなど無いッ。あると便利そうだがな。
よく使われるのは[ SSI ]という方法。HTMLファイルから直接CGIを起動するコトの出来る方法だが、その分セキュリティに問題が発生するため許可していないサーバ(プロバイダ)も多い。
SSIが使えるサーバなら、カウンターを取り付けたいHTMLファイルの任意の場所に

<!--#exec cgi="count.cgi"-->

という記述を加えてやることで、カウンターを動かすことが出来る。
SSIが使えるかどうかはネットワークの管理者(プロバイダの人)に聞いてみるとかすればいい。ホームページ容量なんかをウリにするプロバイダならSSIオッケーというところも多いようだな。
まあ、SSIについての詳細はFAQの方に挙げるつもりでいる。SSIが使えると、やれることが気持ち2倍ぐらいに増える! ・・・がもっともセキュリティとかに関する注意も2倍払わなきゃイカンがな。
ミナ うまい話なんてないってコトですね・・・。
先生 内容が難しかったせいか、なんかヘコみ気味だなミナくん・・・。最初の前向きトークはドコへ?

< Back to Index
[ Sample ] [ Source]