PHPでカウンターの作り方
phpで自作カウンターを作るスクリプトをまとめてみました。
ほとんど、参考サイト様のを丸写しのスクリプトになっていますので、ページ後部の参考サイト様に直接飛んで見たほうが理解できるかもしれません。
同一IPをカウントする数字カウンタ
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-Transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <title>シンプルカウンタ</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css; charset=utf-8"" /> <meta http-equiv="Content-Script-Type" content="text/javascript; charset=utf-8"" /> <link rel="stylesheet" type="text/css" href="style.css" media="all" /> </head> <body> <?php $data=file('./data.txt');//テキストファイルを開いて1行ずつ配列で返す $data[0]++;//1行目(カウンタの数字)の値に1を加える $fp=@fopen('./data.txt','w');//テキストファイルを書き込み形式で開く flock($fp,LOCK_EX);//開いたファイルを排他的ロック fputs($fp,$data[0]);//開いたファイルに数値を書き込む fclose($fp);//ファイルを閉じる echo($data[0]); ?> </body> </html>
カウンタの基本の形です。
予めdeta.txtファイルを作っておきましょう。file()関数は、fopenせずにファイルを1行ずつ取得して、配列の形で返してくれます。この場合のdeta[0]は1行目、deta[1]なら2行目の意味です。
似たようなのにfile_get_contents()関数とfgets()関数があります。前者は1行ずつでなく全体を1つの文字列として取得する関数、後者は、一度$fp=fopen()でファイルを開いたあとに、fgets($fp, 1024)のような形で、1行目の1024バイトまでを読み込むというように指定された文字数だけ読み込むことができる関数です。
$data[0]++は、$deta[0]=$deta[0]+1をしているのと同じ事。実行速度の問題です。
続いて、fopen()関数でファイルを開きますが、2番目のパラメータで読み/書きのファイルモードを指定できます。@はor die("")部分(エラーメッセージ)を表示させなくする方法。初回アクセスではファイルもないし、データもないので必ずエラーになるため。
モード | 読み/書き | ファイルポインタ | ファイルが存在しない時 |
---|---|---|---|
r | 読み | 先頭 | エラー |
r+ | 読み/書き | 先頭 | エラー |
w | 書き | 先頭 | 新規作成 |
w+ | 書き/読み | 先頭 | 新規作成 |
a | 書き | 終端 | 新規作成 |
a+ | 書き/読み | 終端 | 新規作成 |
x | 書き | 先頭 | 新規作成(既存の場合エラー) |
x; | 書き/読み | 先頭 | 新規作成(既存の場合エラー) |
flockは、同時に書き込みがされた時に衝突するのを防ぐ目的で、ロックする機能です。
設定値 | 内容 |
---|---|
LOCK_SH | 共有ロック |
LOCK_EX | 排他的ロック |
LOCK_UN | ロックを解除 |
LOCK_NB | ロック中にflock()でブロックさせない |
通常はファイルを読み取るときには共有ロック(読み取りは許可するが書き込みは許可しない)、ファイルを書き込むときには排他的ロックを使用する。
排他的ロックをかけたら、fputs()関数でファイルに2番目のパラメータの内容を書き込む。この場合はw(上書き)モードだから、データは上書きされる。
書き込みが終わったら、fclose()でファイルを閉じて、echoでカウンタの数字を表示させれば終了。
同一IPをカウントしない数字カウンタ
上記の応用編になります。最初の3行は設定部分です。
//略 <body> <?php $log="./data.txt"; $fig=5; //桁数 $ipcheck=1; //連続IPカウントしない?yes=1,no=0 $ip=$_SERVER['REMOTE_ADDR'];//ipアドレスの取得 $data=file($log);//テキストファイルを1行読み込んで配列に。 list($count,$addr)=explode("|",$data[0]);//explodeで$data(例:5200|192.162.11.1)を分割後配列にする。その配列を順番に$countと$addrに入れる。 if(($ipcheck==1 && $ip!=$addr)||$ipcheck==0){ //連続IP×モードでIPが重複していない(初回アクセス)、または、ipカウントがOFFなら $count++; $aaa=implode("|",array($count,$ip));//カウンタとIPを|でつなげて変数に代入 $fp=@fopen($log,'w');//書き込み形式でファイルを開く。 flock($fp,LOCK_EX); fputs($fp,$aaa); fclose($fp); } $bbb = sprintf('%0'.$fig.'d', $count) . '人目'; echo($bbb); ?> </body> </html>
$_SERVER['REMOTE_ADDR']は、サーバーから返されるIPアドレスを取得するサーバー変数です。これにより変数に192.168.11.1のようなIPアドレスが入ります。
list($count,$addr)=explode("|",$data[0])の部分。
explodeは文字列を分割する関数。explode(" ",10 20)なら、10 20という半角スペース入のデータを半角スペースで切って配列として返してくれます。
list(a,b)=array(c,d)は、配列の値(cとd)を変数(aとb)に順番に入れてくれる関数。$a=array[0]、$b=array[1]を短縮した形。
テキストファイルの1行目が、来客数|IPアドレスのような形になっているので、それを分割して別々の変数に入れるという作業。
if文では、IPアドレスのチェックを行います。同一IP×モードでipアドレスがテキストファイルのipと同じでなければ、又は、同一IP○モードであれば、カウンタを1プラスする。 &&はandと同じ、||はorと同じ、!=はnotイコールの意味。
新しいIPアドレスとカウンタの数値を配列に入れて、implode(exploadの逆)で結合し、ファイルの内容を上書きする。
sprintf("a","b")で、カウンタの数字(b)を5桁(a)に整形し、変数へ。echoで表示して終了。
同一IPをカウントしない画像カウンタ
文字の部分を画像に置き換えるスクリプトです。今までとは別に、0~9までの画像(名前は数値.gif=0.gifなど)を用意する。
//略 $bbb = sprintf('%0'.$fig.'d', $count) . '人目'; //以下追加部分 for($i=0; $i<strlen($bbb); $i++){ $ccc=substr($bbb,$i,1); echo("<img src='./gif1/$ccc.gif'>\n"); ?> </body> </html>
前のスクリプトのecho($bbb)を消して、何行かのスクリプトを追加します。
strlenは文字列の桁数を取得する関数で、$iは5よりも小さい間、$iを1ずつプラスしていくという繰り返し処理がfor文。
substrで$bbbの$i文字目から1文字を抽出する。これにより$cccに5桁の数値の1文字目からの数値が順番に代入される。
そしたら、それをimgタグに関連付けて表示させれば終了。改行タグがあるといい具合に文字間隔が開く。
同一IPをカウントしない昨日・今日カウンタ
合計○人、昨日○人、今日○人と表示させる、昨日・今日カウンタを作成します。
//略 <body> <?php $log="./data.dat"; $fig=5; //桁数 $ipcheck=1; //連続IPカウントしない?yes=1,no=0 $ip=$_SERVER['REMOTE_ADDR'];//ipアドレスの取得 $data=file($log); list($tal,$tday,$yday,$dy,$addr)=explode(" ",$data[0]); // 保存データ分割(トータル、今日、昨日、日付、IP) if(($ipcheck==1 && $ip!=$addr)||$ipcheck==0){ if(date("j")!=$dy){ $dy=date("j"); $yday=$tday; $tday=0; } $tal++; $tday++; $aaa=implode(" ",array($tal,$tday,$yday,$dy,$ip));//カウンタとIPを|でつなげて変数に代入 $fp=@fopen($log,'w');//書き込み形式でファイルを開く。 flock($fp,LOCK_EX); fputs($fp,$aaa); fclose($fp); } $bbb=sprintf('合計%05d 昨日%03d 今日%03d',$tal,$yday,$tday); echo($bbb); ?> </body> </html>
今回は、トータル、今日、昨日、日付、IPと保存内容が多めになります。半角スペースで区切り、datファイルに保存しています。
date(a,b)関数は、2番目のパラメータで取得した時間を1番目のパラメータで整形してくれる関数です。 2番目を省略すると、2番目はtime()=(現在の時間を1970年~の秒数で取得)になります。
小文字のjで現在の日付を頭に0を付けない状態で取得します。 取得した日付とdatファイルの日付がイコールでなければ、日付が変わったとみなして、新しい日付に書替え、昨日の日付を今日の日付に直し、今日の日付は0にして、今日の日付とトータルをプラス1する。 あとは、implodeで各データを半角スペースでつなげて保存、sprintfで整形後、echoで表示させて終了。
コメントor補足情報orご指摘あればをお願いします。
- << 前のページ
- 次のページ >>