NAME

GreeseCGI - Greeseを用いたCGI


SYNOPSIS

  use GreeseCGI;
  GreeseCGI::main(
    db => $dsn,
    user => $user,
    password => $password,
    templatedir => $dir,
    charset => $charset,
    verbose => $verbose,
  );


DESCRIPTION


概要

GreeseCGIは、Greeseを用いてテンプレートとRDBデータからHTMLを生成する機能と、HTMLフォームによってRDBデータを検索・挿入・更新・削除する機能の、二つの機能を持ったCGIを簡単に作成するためのモジュールです。テーブル定義ファイルからテーブルやインデックスを作成するとともに、テンプレートを自動生成する機能も持っています。


CGIスクリプトの作成

GreeseCGIを用いたCGIスクリプトは、例えば次のようになります。

  #!/usr/bin/perl
  use GreeseCGI;
  GreeseCGI::main(
    db => 'dbi:SQLite:dbname=testdb',
    templatedir => '/usr/local/Greese/test',
    charset => 'Shift_JIS',
  );

この例では、DBD::SQLiteを用いてtestdbというデータベースに接続し(ユーザー名やパスワードは無し)、/usr/local/Greese/testにあるテンプレートを使うように指示しています。また文字コードにシフトJISを指定しています。

これだけで、このCGIスクリプトは、GreeseテンプレートとRDBデータからHTMLを生成する機能と、HTMLフォームによってRDBデータを挿入・更新・削除する機能を持つことになります。あとは、テンプレートとHTMLフォームを用意するだけです。

このCGIがGETで呼ばれたときは、CGIパラメータで指定されたGreeseテンプレートに基づいて生成したHTMLを返します。POSTで呼ばれたときは、CGIパラメータで指定された命令やフィールド名と値の組にしたがって、テーブルを作成したり、データが検索・挿入・更新・削除され、その結果を表示するHTMLを返します。

※下記の「利用の手順」もご覧ください。


GreeseCGI::main()の引数

GreeseCGI::main()の引数はハッシュの形で、次のキーによって指定します。※は必須です。

  db            DBIのDSN※
  user          データベース接続の際のユーザ名
  password      データベース接続の際のパスワード
  templatedir   テンプレートファイルのあるディレクトリ※
  charset       文字コード※
  templateclass Greeseのテンプレートクラス名
  filedir       添付ファイルの保存されるディレクトリ
  fileurl       上記ディレクトリを表すURL
  verbose       真に指定すると実行結果表示にSQL文やDBIのエラーコードが付加される

templateclassを省略するとGreese::Template::Htmlが使われます。独自のテンプレートクラスを使用したい場合にtemplateclassで指定します。

このほかにも指定できる引数がありますが、下記のそれぞれの機能の項で説明します。


GETの場合のCGIパラメータ

GETで呼び出す場合のCGIパラメータは、次のとおりです。※は必須です。

  template    テンプレートファイル名※
  page        テンプレートがページ分割されているときのページ番号
  where       テンプレートに追加で渡されるwhere条件
  table       templateに.csvを指定した時の対象テーブル名
  .makehtml   真を指定すると静的HTMLファイル生成

上記以外のCGIパラメータもすべてテンプレートに渡されます。

テンプレートファイルの書き方は、Greeseのドキュメントをご覧ください。

templateに'.csvup'、'.csvdown'、'.create'を指定した場合と、.makehtmlを指定した場合は特殊で、必要なページをGreeseCGI自身で生成して返します。テンプレートファイルを用意する必要はありません。

'template=.csvup'と指定した場合は、下記のPOSTでのcsvコマンド(CSVファイルによるデータアップロード)のための入力ページを生成して返します。tableパラメータでテーブル名を指定した場合はそのテーブルが対象となり、tableパラメータを省略した場合はテーブル名の入力欄がページに含まれます。

'template=.csvdown'と指定した場合は、tableパラメータで指定したテーブル名のテーブルの全データをCSV形式で表示するページを生成して返します。

'template=.create'と指定した場合は、下記のPOSTでのcreateコマンド(テーブル構造を記述したファイルをアップロードしてテーブル作成とテンプレート自動生成をおこなう)のための入力ページを生成して返します。

'.makehtml=1'と指定した場合は、テンプレートとデータベースから生成されたページをHTMLファイルとして保存します。具体的な方法は後述します。


POSTの場合のCGIパラメータ

POSTで呼び出す場合のCGIパラメータは、ピリオドで始まるものはGreeseCGIへのコマンド、そうでないものはカラム名とみなされます。(下記のカラムタイプを参照のこと。)GreeseCGIへのコマンドは次のとおりです。※は必須です。

  .command    操作名※
  .password   実行許可のためのパスワード
  
  ○以下は.commandが'insert', 'update', 'delete'の場合
  .password_field  パスワードを保持しているカラム名
  .template_ok 実行に成功した場合に返されるHTMLを生成するテンプレートファイル名
  .msg_ok     実行に成功した場合に返されるHTMLに含まれるメッセージ文字列
  .url_ok     実行に成功した場合に返されるHTMLのOKボタンで移動するURL
  .template_error 実行に成功した場合に返されるHTMLを生成するテンプレートファイル名
  .msg_error  実行に失敗した場合に返されるHTMLに含まれるメッセージ文字列
  .url_error  実行に失敗した場合に返されるHTMLのOKボタンで移動するURL
  
  ○以下は.commandが'select'の場合
  .template   結果表示のためのテンプレートファイル名※
  .andor      各項目の検索条件をANDとORどちらで結合するか(省略するとAND)
  .op_項目名  値を比較する演算子(省略すると = )
  
  ○以下は.commandが'csv'の場合
  .csvtable   CSVファイルで値を投入するテーブル名※
  .csvfile    CSVファイル名(<input type="file" name=".csvfile"...>)※
  .cleartable 真だとテーブル内容を削除してからデータを投入
  
  ○以下は.commandが'create'の場合
  .datafile   データファイル名(<input type="file" name=".datafile"...>)※
  .templateonly 真だとテンプレート作成のみをおこなう
  .notemplate 真だとテンプレート作成をおこなわない

.commandで与える操作名は次のいずれかです。

  select … 検索
  insert … 挿入
  update … 更新
  delete … 削除
  csv    … CSVデータによる挿入
  create … テーブル作成

.commandがinsertかudateの場合、「.」で始まらないパラメータ名はカラム名とみなされて、その値がカラムにセットされます。同じカラム名のパラメータが複数あった場合、その値をカンマ区切りで並べたものがセットされます。区切りのカンマはmain()のmultivalue_separator引数で変更できます。

.passwordで与えるパスワードは、この挿入、更新、削除操作の実行のためのパスワードであり、その照合対象は.password_fieldパラメータか後述の*_password引数で与えます。このパスワードをデータベース接続のためのパスワードと混同しないようにしてください。

.password_fieldは、そのレコード内にパスワードが保存されている場合に、そのカラム名を指定します。この指定をおこなうと、.password_fieldで与えられたカラムの値と.passwordで与えられたパスワード文字列との合致条件がwhere節に追加されます。パスワードが合致しない場合はエラーとはならず、操作の結果変更されたレコード数が0となります。

.template_okを指定した場合は.msg_okと.url_okは使われません。.template_errorを指定した場合は.msg_errorと.url_errorは使われません。.template_okと.template_errorで指定したテンプレートには、操作対象のレコードを限定する条件がwhereパラメータで渡されます。

.url_okや.url_errorに'close()'を指定すると、OKボタンでウィンドウが閉じます。'back()'を指定すると、OKボタンで前の画面に戻ります。省略すると'back()'とみなされます。

.commandが'select'の場合は、「.」で始まらないCGIパラメータ名が項目名とみなされ、その値によって「``項目名'' = '値'」のような検索条件が、.templateで指定したテンプレートファイルに渡されるwhereに付加されます。項目名の頭に「#」を付けると数値項目とみなして値を「'」で囲みません。値の比較演算子は、「.op_項目名」(項目名が「名前」なら「.op_名前」)というパラメータがあればそれが使われ、なければ「=」になります。比較演算子に「like」を指定した時に、値に「%」を含まなければ、自動的に値の前後に「%」が付加されます。whereに付加される時のAND、ORは、.andorパラメータがあればそれを使い、なければANDになります。

.commandが'csv'の場合は、.csvtableで指定したテーブルに、.csvfileで指定したCSVファイルのデータが挿入され、その結果を表示する画面が返されます。.cleartableが真だとCSVファイルによるデータ挿入の前にテーブルの内容がすべて削除されます。CSVファイルの先頭行は項目名のリストでなければなりません。二行目以降はデータ行となり、テーブルへinsertされます。先頭行で指定した項目数とデータ数が一致しない行はエラーと表示され、insertされません。

.commandが'create'の場合は、.datafileで指定したテーブル定義ファイルから読み取った指定に従ってテーブルが作成されます。また、テーブルを閲覧、編集、挿入するためのテンプレートが自動的に生成されます。テーブル定義ファイルの書式とテンプレート作成については後述します。.templateonlyに真が指定されていると、テーブルの作成は行われず、テンプレート作成のみが実行されます。.notemplateに真が指定されていると、テーブル作成のみが行われてテンプレート生成は行われません。


GreeseCGI::main()の引数によるPOSTの認証や権限制御

POSTの際の.commandパラメータで指示する操作名に対応して、GreeseCGI::main()の「操作名_password」という引数でパスワードを指定しておくと、それが .password パラメータの値と一致しないと操作が実行されません。例えばGreeseCGI::main()の引数で create_password => 'abc123' と指定しておけば、.commandがcreateの操作は、その時に指定された.passwordの値が'abc123'でなければ実行されません。

POSTの際の.commandパラメータで指示する操作名に対応して、GreeseCGI::main()の「操作名_allowuser」という引数でカンマ区切りのユーザー名リストを指定しておくと、Webサーバーの認証機能またはGreeseCGIのクッキー認証によって認証されたユーザー名がそのリストの中にないと操作が実行されません。例えばGreeseCGI::main()の引数で insert_allowuser => 'admin' と指定しておけば、.commandがinsertの操作は、ユーザー名'admin'で認証していなければ実行されません。

POSTの際の.commandパラメータで指示する操作名に対応して、GreeseCGI::main()の「操作名_allowgroup」という引数でカンマ区切りのユーザー名リストを指定しておくと、GreeseCGIのクッキー認証によって認証されたグループ名がそのリストの中にないと操作が実行されません。例えばGreeseCGI::main()の引数で update_allowgroup => 'admin' と指定しておけば、.commandがupdateの操作は、グループが'admin'のユーザーで認証していなければ実行されません。


クッキー認証

GreeseCGI::main()のauth引数を指定すると、クッキーを使用した、ユーザー名とパスワードによる認証を行うことができます。auth引数には次のようなハッシュ参照を指定します。

  {
  template => 認証入力画面テンプレートファイル名,
  checkpass => 認証サブルーチン参照,
  makecookie => クッキー作成サブルーチン参照,
  checkcookie => クッキー検査サブルーチン参照,
  noauthcommands => 認証不要コマンド名の配列参照
  }

auth引数を指定したCGIプログラムが呼び出されると、まずクッキー検査サブルーチンが実行されます。クッキー検査サブルーチンは認証が必要かどうか判断して、認証が必要で正しいクッキーがあればそこからユーザー名とグループ名を得てauthuserとauthgroupというパラメーターにセットします。認証が必要で正しいクッキーがなければ、認証入力画面テンプレートに従ってユーザー名とパスワードの入力画面が返されます。入力されたユーザー名とパスワードは認証サブルーチンで検査され、OKならクッキー作成サブルーチンで作成されたクッキーがセットされて元のURLが呼び出されます。

「認証入力画面テンプレートファイル名」は、ユーザー名とパスワードを入力する画面のテンプレートファイル名を指定します。このテンプレートには、orgurlとrealmの二つの外部パラメータが渡され、次のフォームパラメータをPOSTで送信しなければなりません。

  .command … auth
  orgurl … 外部パラメータorgurlの値
  realm … 外部パラメータrealmの値
  user … ユーザー名
  password … パスワード

「認証サブルーチン参照」は、(realm, ユーザー名, パスワード) を引数にとり、(認証結果, グループ名) を返すサブルーチン参照を指定します。「認証結果」は認証した場合「OK」、ユーザー名かパスワードが違う場合「NO」、何らかのエラーの場合はそのエラーメッセージそのものとします。「認証結果」が「OK」の場合は「グループ名」も返さねばなりません。認証をどういうファイルやデータベースに基づいておこなうかは認証サブルーチンに任されています。

「クッキー作成サブルーチン参照」は、(CGIオブジェクト, realm, ユーザー名, グループ名) を引数にとり、作成されたクッキー文字列を返すサブルーチン参照を指定します。クッキーをどういう内容にするかはクッキー作成サブルーチンに任されていますが、ユーザー名とグループ名が取り出せること、有効期限管理ができるように日時情報を入れること、第三者による作成ができないように秘密キーを含むダイジェストを含めること、が必要です。

「クッキー検査サブルーチン参照」は、(CGIオブジェクト, main引数ハッシュ) を引数にとり、(検査結果, realm, エラーメッセージ, ユーザー名, グループ名) を返すサブルーチン参照を指定します。「検査結果」は、認証の必要のない場合と正しいクッキーがあった場合「OK」、所定のクッキーがないかクッキーの内容が期限切れなど正しくない場合「NO」、何らかのエラーの場合「ERROR」とします。「検査結果」が「OK」の場合、realm、ユーザー名、グループ名も返さねばなりません。「検査結果」が「ERROR」の場合、「エラーメッセージ」も返さねばなりません。認証が必要かどうか、必要な場合のrealm名、クッキーの検査といった具体的な処理はクッキー検査サブルーチンに任されています。

クッキー検査サブルーチンが「OK」を返した場合、ユーザー名とグループ名がパラメータauthuserとauthgroupにセットされます。

次にauth指定と各サブルーチンの例を示します。

  auth => {checkpass => \&checkpass, makecookie => \&makecookie,
    checkcookie => \&checkcookie, template => 'auth.html'}
  
  sub checkpass {
    my($realm, $user, $password) = @_;
    if( checkPasswordInUserDB($realm, $user, $password) eq 'OK' ) {
      my $group = getGroupFromUserDB($realm, $user);
      ('OK', $group);
    } else {
      'NO';
    }
  }
  
  sub makecookie {
    my($cgi, $realm, $user, $group) = @_;
      my $date = getCurrentDateString();
      my $key = md5_base64("$realm:$group:$user:$date:$SecretKey");
      [$cgi->cookie(realm => $realm), $cgi->cookie(group => $group),
        $cgi->cookie(user => $user), $cgi->cookie(key => $key)];
  }
  
  sub checkcookie {
    my($cgi, %cfg) = @_;
    my $result = 'NO';
    my $realm = $Realm;
    my($msg, $user, $group);
    my $crealm = $cgi->cookie('realm');
    $group = $cgi->cookie('group');
    $user = $cgi->cookie('user');
    my $key = $cgi->cookie('key');
    if( $crealm && $user && $key ) {
      $realm = $crealm;
      my $date = getCurrentDateString();
      if( md5_base64("$realm:$group:$user:$date:$SecretKey") eq $key ) {
        $result = 'OK';
      } else {
        $result = 'ERROR';
        $msg = "User $user has no authority for this page"
      }
    }
    ($result, $realm, $msg, $user, $group);
  }


独自の.commandの追加

GreeseCGI::main()にcustom_command引数を与えることで、POSTの際の.commandに独自のものを追加できます。custom_command引数として、コマンド名とサブルーチン参照の組のハッシュ参照を与えます。このサブルーチン参照のサブルーチンは(CGIオブジェクト, main引数ハッシュ参照)を引数として呼び出され、(タイトル, メッセージ, URL)を返さねばなりません。追加された.commandでPOSTされると、対応するサブルーチンが呼び出されて、返されたタイトルとメッセージと「OK」ボタンによる画面が表示され、「OK」ボタンをクリックすると返されたURLへ移動します。URLとして「close()」を指定すると画面を閉じ、「back()」を指定すると前の画面へ戻る動作となります。

たとえば次のようになります。

  GreeseCGI::main(..., 
    custom_command => {mail => \&mail});
  
  sub mail {
    my($cgi, $cfg) = @_;
    my $msg = sendmail($cfg->{mailfrom}, $cfg->{mailto}, 
      $cgi->param('subject'), $cgi->param('body'));
    ('メール送信結果', $msg, 'close()');
  }

独自のコマンドについてクッキー認証が不要な場合、noauthcommandsで指定しておきます。


カラムタイプによる付加記号

POSTの場合のCGIパラメーターのカラム名は、文字列型のカラムの場合はそのまま指定すればOKですが、数値型のカラムの場合は「#カラム名」と前に#記号を付けて指定します。

挿入の場合に「##カラム名」と#記号を二つ付けたカラム名の指定があると、そのカラムの既存の値の最大値より1大きな値がセットされます。

※##指定をする場合、データ挿入時にテーブルロックが必要となります。そのためのSQL文が必要であれば、main()のlocktablesql引数で指定しておきます。

挿入や更新の場合に「@カラム名」と@記号を付けたカラム名があると、その時点の日時文字列(yyyy-mm-dd hh:mm::ssの形式)がセットされます。

挿入や更新の場合に「&カラム名」と&記号を付けたカラム名があると、ファイルアップロード項目として扱われ、ファイル自体はGreeseCGI::main()のfiledir引数で与えたディレクトリに連番のファイル名で保存され、ファイル名が項目の値にセットされます。(拡張子はアップロードされたファイル名の拡張子と同じものになります。)


createのためのテーブル定義ファイルの書式

POSTで.commandパラメータにcreateを指定した時に、.datafileで指定するテーブル定義ファイルは、次のような書式になります。

テーブル定義

「def テーブル名」から「enddef」までの間に、カラム名、タイプ、表示幅、検査指定 をタブ区切りで並べた行を並べます。行頭にもスペースやタブを入れて構いません。

カラム名の頭に「*」を付けると、インデックスが付けられます。

タイプは、実際に使用するRDBに応じて適切なものを指定します。primary keyなどの指定も可能です。(テンプレートの自動生成のためにはどれかの項目にprimary keyの指定が必要です。)タイプの頭に「@」「@@」「##」「#」「&」の記号を付けることができ、自動生成されるデータ挿入・編集テンプレートでのカラム名指定に反映されます。「@@」は挿入時のみに日時がセットされ、「@」は挿入時と更新時に日時がセットされます。

表示幅は、自動生成されるデータ挿入・編集テンプレートでのそのカラムの表示幅または選択肢で、表示幅の場合は半角文字数または「文字数,行数」の形で指定します。表示幅は省略しても構いません。選択肢の場合は「[a,b,c]」のように[]の中に選択肢をカンマ区切りで並べます。複数選択可の場合は「[a,b,c]m」のように後ろに「m」を付けます。他のテーブルからselectして選択肢とする場合は、「*[select(…)]*,値カラム名,表示文字列」と指定します。*[select(…)]*はGreeseのselect命令、値カラム名は<option>のvalue属性となる値のカラム名、表示文字列は<option>の内容となる文字列で*[カラム名]*を含めることができます。複数選択可の場合は「*[select(…)]*,値カラム名,表示文字列,m」と最後に「,m」を付けます。

表示幅の先頭に「+」を置くと、その項目は自動生成されるテーブル内容閲覧画面に表示されます。primary key指定された項目はこの指定をしなくても必ずテーブル内容閲覧画面に表示されます。

検査指定は、自動生成されるデータ挿入・編集テンプレートでの送信前のJavaScriptによるそのカラムの値のチェックの指定です。「/正規表現/``エラーメッセージ''」と指定すると、正規表現に合致しない時にエラーメッセージが表示されます。「.``エラーメッセージ''」と指定すると、カラム値が空の時にエラーメッセージが表示されます。

表示幅として選択肢を指定した場合は検査指定はしないでください。

具体例をあげます。

  def 住所録
    番号      ##int primary key
    登録日時  @@text +
    更新日時  @text +
    名前      text  +20     ."名前は必須"
    住所      text  +60,3
    年齢      #int  +5      /^\d+$/"年齢は半角数字で入力"
    性別      text  +[男,女]
    グループ  int   +*[select(from "グループ")]*,番号,*[番号]* *[名前]*
    画像      &text 60
  enddef

タイプとして「listtable(…)」を指定すると、そのテーブルと一対多の関係になる値を別テーブルに格納することができます。「listtable(リストテーブル名, 第一カラム名 型,第二カラム名 型,*[select(…)]*,表示文字列」と指定します。リストテーブル名はデータが格納される別テーブルの名前、第一カラム名と型はdefで定義中のテーブルのprimary keyカラム値がセットされるカラムの指定、第二カラム名と型は値がセットされるカラムの指定、*[select(…)]*はdefで定義中のテーブルでこの項目の値を表示する時の*[select(…)]*、表示文字列はその時の表示文字列です。listtable指定をする時は表示幅として複数選択可の選択肢を指定しなければなりません。

具体例をあげます。(listtableの箇所は一行で書くべきところを見やすいように改行を入れて書いてあります。)

  def グループ
    グループ番号 int primary key  4
    グループ名   text  +20
  enddef
  def ユーザー
    ユーザー番号 int primary key  4
    ユーザー名   text  +20
    グループ     listtable(groups,usernum int,groupnum int,
      *[select(from groups,"グループ" where groupnum = "グループ番号"
      and usernum = %[ユーザー番号]%)]*,*[グループ名]*),
      *[select(from "グループ")]*,グループ番号,*[グループ名]*,m
  enddef

この例の場合、自動生成されるテンプレートでユーザーテーブルの挿入・編集の際にグループ項目はグループテーブルのグループ名の値のリストから複数選択するようになります。そして選択されたグループ名に対応するグループ番号が、ユーザー番号との組でgroupsテーブルに格納されます。例えば次のようになります。

  "グループ"テーブル
  グループ番号 グループ名
  ------------ ----------
  10           Agroup
  20           Bgroup
  30           Cgroup
  
  "ユーザー"テーブル
  ユーザー番号 ユーザー名
  ------------ ----------
  100          Foo
  200          Bar
  
  "groups"テーブル
  usernum groupnum
  ------- --------
  100     10
  100     30
  200     20
  200     30

インデックス定義

複数カラムのインデックスを定義したい場合は、「index テーブル名 カラム名1,カラム名2,...」のような行で指定します。

データ定義

「data テーブル名」の後に、タブ区切りのカラム値を並べた行を行頭にもタブを置いて書き並べます。すべてのカラムに対して値を指定しなければなりません。

任意のSQL文の実行

「sql SQL文」の行があると、そのSQL文が実行されます。


createの際の自動テンプレート生成

POSTで.commandパラメータにcreateを指定した時に、.datafileで指定するデータファイルから読み取られた指定に従って、次のHTMLテンプレートファイルが、テンプレートディレクトリ内に作成されます。(テンプレートディレクトリがcgiプログラムから書き込み可能でなければなりません。)

  default.html … ホームページ
  tableX.html  … テーブル内容一覧
  tableXi.html … テーブルへのデータ挿入
  tableXv.html … テーブルのデータ閲覧
  tableXe.html … テーブルのデータ編集
  ※Xは.datafileで指定されたテーブルの順番(0から始まる)

各テーブルのページはdefault.htmlからたどれるようになっています。


データ更新時のコールバック

データを挿入・更新・削除する際(POSTの.commandパラメータがinsert、update、deleteの時)、更新前や更新後に指定のサブルーチンを呼び出すようにすることができます。これにより、入力された値の書式や範囲のチェック、文字種や書式の変換などの処理を行うことができます。

更新前のコールバックは、GreeseCGI::main()のbeforeupdate引数に、{テーブル名 => サブルーチン参照} という形のハッシュ参照を指定します。すると、指定のテーブルに対して挿入または更新される前に、指定のサブルーチンが呼び出されます。サブルーチンに渡される引数は、(CGIオブジェクト, タイプ, main引数ハッシュ参照, テーブル名, セットされる予定の値, WHERE句) となります。「タイプ」はinsert、update、deleteです。「セットされる予定の値」はカラム名と値の組のハッシュ参照です(deleteの場合は渡されません)。サブルーチンは、(結果, セットされる値) を返さねばなりません。「セットされる値」はカラム名と値の組のハッシュ参照です。「結果」として'OK'を返すと「セットされる値」に従って挿入・更新されます。「結果」として'OK'以外の文字列を返すと、エラーが発生したものとみなされてその文字列が画面に表示され、データの挿入・更新・削除は行われません。

たとえば次のようになります。

  GreeseCGI::main(..., 
    beforeupdate => {'名簿' => \&check});
  
  sub check {
    my($type, $cfg, $table, $values, $where) = @_;
    if( $values->{'生年月日'} =~ /^(\d+)\/(\d+)\/(\d+)$/ ) {
      $values->{'生年月日'} = sprintf "%04d/%02d/%02d", $1, $2, $3;
      return ('OK', $values);
    } else {
      return '生年月日はy/m/dの形式で入力してください';
    }
  }

更新後のコールバックは、GreeseCGI::main()のafterupdate引数に、{テーブル名 => サブルーチン参照} という形のハッシュ参照を指定します。すると、指定のテーブルに対して挿入または更新が成功した後に、指定のサブルーチンが呼び出されます。サブルーチンに渡される引数はbeforeupdateの場合と同じです。このサブルーチンの返値は使われません。


静的HTML生成

テンプレートから生成された内容をHTMLファイルとして保存することができます。そのためには、GreeseCGI::main()に、htmldir、htmlurl、topleveltemplates、nomakehtmlの各引数を指定します。各引数の意味は次の通り。

  htmldir … 生成されたHTMLファイルが格納されるディレクトリ
  htmlurl … 上記ディレクトリのURL
  topleveltemplates … HTML生成の起点となるテンプレートファイル名の配列参照
  nomakehtml … 対象外のテンプレートファイル名の配列参照

そして、cgiを.makehtml=1のパラメータを与えてGETで呼びます。すると、topleveltemplatesで指定された各テンプレートに、.makehtml以外のcgiパラメータを与えて生成された内容がHTMLファイルとしてhtmldirで指定したディレクトリに保存されます。その際、生成された内容に「 href=``cgiのURL?…''」というリンクがあれば、そのcgi呼び出しで生成される内容もHTMLファイルとして保存され、リンク先はそのHTMLファイルのURLに置き換えられます。ただし、templateパラメータで指定されたテンプレートファイル名がnomakehtmlで指定されていた場合は、HTML生成とリンク置き換えは行われません。このリンク置き換え処理は再帰的に行われます。

生成されるHTMLファイルのファイル名は、テンプレートファイル名のボディ部の後に、ソートされたパラメータ名とその値の組を、「_」を区切りとして並べ、テンプレートファイル名の拡張子を付けたものになります。たとえば、「…/foo.cgi?template=bar.html&where=num=2」というcgi呼び出しで生成される内容は「bar_where_num=2.html」というファイルに保存されます。


利用の手順

典型的な利用の手順は次のようになります。

  1. 利用するRDBの準備

    DBIから利用できるRDBなら基本的に利用できます。DBIモジュールと利用するRDBに対応したDBDモジュールをインストールします。必要であればデータベースのサーバープロセスを起動したり、使用するデータベースを作成したりしておきます。

    小規模なものならSQLiteを使うと、あらかじめサーバープロセスを起動しておくと言った手間がないのでお手軽です。

  2. テーブル定義ファイルの作成

    データベースを設計し、上述の「createのためのデータファイルの書式」に従ってテーブル定義ファイルを作成します。

  3. CGIスクリプトの作成・設置

    上述の「CGIスクリプトの作成」「GreeseCGI::main()の引数」に従って、CGIスクリプトを作成し、実行できる状態に設置します。あわせて、テンプレートを置くディレクトリも用意し、CGIから書き込める状態にしておきます。

  4. テーブル作成

    Webブラウザから、CGIスクリプトをtemplate=.createで呼び出し、2.で作成したテーブル定義ファイルをアップロードして、テーブルを作成します。このとき、テンプレートディレクトリに自動的にテンプレートが作成されます。これで、CGIスクリプトをtemplate=default.htmlで呼び出せば、各テーブルについて閲覧、挿入、編集、CSVアップロードといった基本的な管理は行えるようになります。必要に応じてCSVファイルでデータ投入をおこないます。

  5. テンプレート作成

    アプリケーションの必要に応じてテンプレートを作成します。


AUTHOR

中島 靖 <nakajima@netstock.co.jp>


SEE ALSO

Greese