シンプルなWebアプリなCGIを書いてみる
今ぱどタウンの古い仕組みをOOなPerlでラッピングしていて、そろそろ情報取得まわりは一段落。1つ1つのCGIを書き直して行くのに、フレームワークがあった方がいいなと構築中なわけだが、1度自分がCGIでよく書くパターンをまとめてみた。
CGIとは〜〜だというのはたくさん答えがあるだろうけど、自分的には「ユーザからの入力をチェックして画面にだす」ものだというのがしっくりくる。当たり前のことを書いているようだがMVCモデルでいうコントローラーの作成がCGIだと。んで、この「チェックをして画面にだす」というところで入力不足でエラーだった場合にどのようにユーザフレンドリーに知らせるかが1つのポイントだと思う。
簡単によく書くパターンでCGIを書いてみた。郵便番号を入力するとそのまま表示する超シンプルなWebアプリとなってます。(CGIのソース、入力画面テンプレート、完了画面テンプレート。PerlのモジュールはHTML::TemplateとHTML::FillInFormが必要です)
このページで、わざと郵便番号ではない数字を入力して送信すると

このような形でエラーが報告されます。フォームの上部にエラーをまとめて表示して、入力した文字列もそのままHTML::FillInFormで復元されてます。簡素なエラー画面でブラウザの戻るボタンを押す必要もありません。戻るボタンを押したときにいままで入力していた物がなくなっているということもないです。まぁ、ほとんどはHTML::FillInFormのおかげなんですけどね。
エラーを画面に出す部分は、入力画面テンプレートの
<!-- TMPL_LOOP NAME=err --><!-- TMPL_IF NAME=__first__ --><ul class="error_list"><!-- /TMPL_IF --> <li><!-- TMPL_VAR NAME=val ESCAPE=HTML --></li> <!-- TMPL_IF NAME=__last__ --></ul><!-- /TMPL_IF --><!-- /TMPL_LOOP -->
の部分。HTML::Templateのloop_context_vars機能を使って、エラーがないときに影響がでないようにしています。あと、テンプレートにはフォーム中にhiddenでmodeの設定をいれてます。
CGIの構造は、よけいな部分を消して書くと
1 #!/usr/bin/perl
2 use strict;
3 use CGI;
4 my $q = CGI->new;
5 my @err;
6 if($q->param('mode') eq "reg"){
7 push(@err,"郵便番号が正しく入力されていません") unless($q->param('zip') =~ /^?d{7}$/);
8 if($#err == -1){
9 #完了画面出力
10 exit;
11 }
12 }
13 $q->param('err',[map{{val=>$_}} @err]);
14 #通常画面出力
15 my $tmpl = HTML::Template->new(
16 filename => 'index.tmpl.html',
17 loop_context_vars=>1,
18 die_on_bad_params=>0,
19 associate=>$q
20 );
21 my $fif = HTML::FillInForm->new;
22 print $q->header(
23 -charset=>'EUC-JP',
24 -expires=>'now',
25 -pragma=>'no-cache',
26 -cache_control=>'no-cache'
27 );
28 print $fif->fill(scalarref=>?$tmpl->output,fobject=>$q,target=>'form1');
のようになっています。5行目でエラー報告用配列をつくり、6行目で「mode」によって分岐。7行目で郵便番号のチェックをして入力エラーがあればエラーの内容をエラー報告用配列にpushする。
8行目でエラー配列をチェックして配列の要素数が「-1」つまりエラーがなければ完了画面を出力してexit。エラーがある場合やmodeがregではない場合は入力フォームの出力へ。データはすべてHTML::TemplateとHTML::FillInFormへはCGIオブジェクトのパラメーターで渡されます。こんな形でエラーの表示と入力情報の復元を実現します。
かんたんなアプリケーションについては大体こんな感じで書いてきました。プログラムの見通しという面では上から下へと手続き型に書いてあるので、まぁmodeの部分が分かれば悪くないと思ってますが、modeが増えたとき(入力確認画面など)のプログラムが非常に難解で見通しの悪いものになることも事実。
もっと大きなプログラムを構築したり、1つのCGIで行うことが増えた時や複数人での開発にはやはりフレームワークがあった方がいいのかもとようやく気づき今構築中。CGI::Applicationをもっと簡単にしたようなもので今までのイメージを崩さないで使えることを目指してます。ぱどタウンとべったりな所を整頓して具合良ければまたここに書きます。