Perl/ActivePerl For UNIX/Linux/Windows
 
TryThe Homepage
初めてのCGI
CGI 研究室
ダイナミックCGI
ダウンロード
サービス
サーバ構築(Windows)
データベースアクセス
有料サービス
FAQ
お問い合わせ
このページを印刷
DBM へのアクセス
DataBase Management(DBM)は、連想配列に結合してランダムにアクセス可能なファイルシステムで、 連想配列のキーにアクセスするだけで、レコードの追加、変更が可能になります。
もちろんキーは一意で無ければなりません。重複するキーは上書きされます。
  DBM の操作
  • ファイルの作成は書き込みモードでオープンします。
    dbmopen(HASH, FILENAME, MODE);
    HASHには、結合する連想配列名、FILENAMEは拡張子を省略した名称を付けます。
    (日本語は使用不可)
    Perlのバージョンによって異なりますが、.dbまたは、.dir、.pagの拡張子が自動で付加されます。
    MODEには、オープン時のモードで、読み込み専用なら「0644」、読み書きする場合は、「0666」を指定します。 ファイルを作成する場合は、読み書きモードで無ければなりません。 読み込み専用で存在しないFILENAMEを指定してもファイルは作成されません。
  • クローズ
    DBMファイルのクローズにはdbmcloseを使用します。
    dbmclose(HASH);
    次の例はデータベースpagecntを作成してページのカウントを保存しています。
    dbmopen(%DBM, 'pagecnt', 0666);
        $DBM{$QUERY{'page'}}++;
    dbmclose(%DBM);
    この例ではCGIと同じディレクトリにpagecnt.dbまたは、pagecnt.dir、pagecnt.pagが作成され、 ページの名称と最初のカウント1が書込まれています。
    通常、pagecnt.dir、pagecnt.pagが作成される古いDBMシステムでは、一度に1つのDBMしかオープンできません。 複数のDBMでリレーションを行う場合は、その都度閉じなければなりません。
  • レコードの削除
    DBMデータベースからレコードを削除するにはdeleteを使用します。
    delete(EXPR);
    「news.html」ページのカウントを削除するには、delete($DBM{'news.html'}); とします。
    本来deleteは、連想配列を削除する物ですが、DBMに結合されている連想配列を削除すると、 同時にデータベースからも削除されます。
  • レコードの存在を調べる
    指定したキーのレコードが実際に存在するか調べるにはdefinedを使います。
    defined(EXPR);
    「news.html」ページのカウントが存在するかを調べるには、
    defined($DBM{'news.html'}) && print "存在します。";
    とします。
  ページカウンタの作成
それでは、実際に使用可能なページカウンタを作成してみましょう。
とりあえず、次の機能を持たせる事にします。
  • すべてのページの累計をカウントさせる
  • カウンタは各ページに表示しない
  • 各ページのカウント数は監理者モードで閲覧する
    1. 初期設定部
      #!/usr/local/bin/perl
      require '../cgi-lib/perl-lib.pl';
      Perlのパスと、多機能ライブラリperl-lib.plのパスを指定します。
      # サイトのURL
      # http://及び、ファイル名(index.html等)は省略
      # 【例】www.inforyoma.or.jp/~terra
      $usersite = 'www.tryhp.net';
      トップページのURLを設定します。この時http://や、index.html等のファイル名は省略します。
      # ダミー画像のファイルパス
      $image = '../images/exspc.gif';
      # カウントを保存するデータベース
      # DBMですので拡張子は指定しない
      $dbmfile = 'pagecnt';
      カウントは表示しませんが、CGIは何かを返す必要が有りますので、透明の小さな画像を設定しておきます。
      DBMのファイル名は拡張子を省略しなければなりません。
    2. メインルーチン
      readparts('QUERY', '<>', '');
      if ($QUERY{'page'}) {
          # ページが指定されている場合にだけ記録
          # perl-libのロックに成功すれば書き込み
          # 失敗すればDBMを守る為このアクセスを無視
          if (!dblock($dbmfile)) {
              # 連想配列%DBMをファイルに結合してオープン
              dbmopen(%DBM, $dbmfile, 0666);
              # ページ名のカウントを1プラスして保存
              $DBM{$QUERY{'page'}}++;
              # DBMを閉じる
              dbmclose(%DBM);
              # ロックを解除
              dbunlock($dbmfile);
          }
      }
      ここが、このスクリプトの心臓部で、DBMへのアクセスです。
      最後にダミーの画像を出力します。
      print "Content-type: image/gif\n\n";
      open(IMG,"cgi-images/exspc.gif");
          binmode(IMG);
          binmode(STDOUT);
          print $_ while (<IMG>);
      close(IMG);
      exit;
      ここまででページからのアクセスが有ればDBMデータベースに記録されます。
      一応ここまでのスクリプトをpagecnt.cgiとして保存しておきます。
      各ページへのタグの追加
    とりあえず、カウンタの書き込みまでは作成できましたので、 次にCGIを呼び出すタグをすべてのページに張り付ける必要が有ります。
    <img src=pgcnt.cgi?page=ファイル名>
    このタグをすべてのページの<BODY>から</BODY>の間ならどこでも結構ですので挿入します。
    今回は日本語に対応していませんので、「ファイル名」にはタグを追加するページのファイルのパスを指定してください。 $usersiteを基準にしたパスですので、index.htmlと同じ階層に有るnews.htmlの場合は
    <img src=pagecnt.cgi?page=news.html>
    となり、1つ下のディレクトリ[friend]のnews.htmlなら
    <img src=pagecnt.cgi?page=friend/news.html>
    と設定します。
      監理者閲覧モードの実装
    1. 初期設定に監理者パスワードを追加
      一応、カウンタの閲覧は監理者専用ですので、CGIにパスワードを設定します。
      # 監理者パスワード
      $root = 'abcd1234';
      メインルーチンの前であればどこでも結構ですのでパスワードを設定します。
    2. 一覧表の表示
      readparts('QUERY', '<>', '');
      if ($QUERY{'pw'} eq $root) {
        print "Content-type: text/html\n\n";
        print "
          <html>
          <head>
          <meta http-equiv='Content-Type' content='text/html; charset=shift_jis'>
          <meta http-equiv='Content-Language' content='ja'>
          <title>ページカウンタアクセスログ</title>
          </head>
          <body>
        ";
        # カウンタDBMをオープン
        # 読み込み専用なので0644でアクセス
        dbmopen(%DBM, $dbmfile, 0644);
          # ページの数だけループしてデータを読込む
          foreach $key (keys %DBM) {
            $count = $DBM{$key};
            # 最大値を取得
            $max < $count && ($max = $count);
            # 並び替えの為カウント数を0をサプレスしない
            # 8桁の整数に統一する
            $count = sprintf("%08d", $count);
            # 書式を整えて配列@ACCESSに代入
            $value = "$count\t$key";
            push(@ACCESS, $value);
          }
        # DBMをクローズ
        dbmclose(%DBM);
        # アクセスの多い順に並び替え
        @ACCESS = reverse(sort(@ACCESS));
        print "<table border=0 cellpadding=0><tr><td bgcolor=#708090>\n";
          print "<table border=0 cellspacing=1 cellpadding=4 style='FONT-SIZE:12px'>\n";
            print "<tr>
              <td bgcolor=#C0C0F0 align=center>ページ</td>
              <td bgcolor=#C0C0F0 align=center>カウント</td>
              <td bgcolor=#C0C0F0 align=center>グラフ</td>
              <td bgcolor=#C0C0F0 align=center>ポイント</td>
            </tr>\n";
            foreach (@ACCESS) {
              ($count, $page) = split(/\t/, $_);
              $count += 0;
              print "<tr>";
              print "<td bgcolor=#FFFFFF>$page</td>\n";
              print "<td bgcolor=#FFFFFF align=right>$count</td>\n";
              if ($max) {
                $point = sprintf("%3.1f", int($count / $max * 1000 + 0.5) / 10);
                $barwidth = $point * 50 / 100;
                print "<td bgcolor=#FFFFFF><font color=#FF8080><nobr>";
                foreach (1 .. $barwidth) { print "■"; }
                print "</nobr></font></td>\n";
                print "<td bgcolor=#FFFFFF align=right>$point</td>\n";
              } else {
                print "<td bgcolor=#FFFFFF></td>\n";
                print "<td bgcolor=#FFFFFF></td>\n";
              }
              print "</tr>\n";
            }
          print "</table>\n";
        print "</td></tr></table>\n";
        print "</body></html>\n";
        exit;
      }
      これで完成です。この例では監理者パスワードに[abcd1234]を設定しましたので、 CGIのURLの後ろに?pw=abcd1234を付けてアクセスした場合のみアクセスログが表示されます。
      ページ カウント グラフ ポイント
      DBM.htm 6 ■■■■■■■■■■■■■■■■■■■■ 100.0
      local.htm 4 ■■■■■■■■■■■■■ 66.7
      perl.htm 3 ■■■■■■■■■■ 50.0
      完成品のサンプルスクリプトはこちら。 サンプルがブラウザに表示された場合は「ソース」を表示し、ファイル名を「pagecnt.cgi」に変更して保存してください。
      または、上記リンクを右クリックして、「対象をファイルに保存」を選択し、ファイル名を「pagecnt.cgi」に変更して保存します。
    Copyright 2004 Terra. All rights reserved. No reproduction or republication without written