新トップページへ | Tip

CGIの作成方法(HTMLのフォームタグ&PerlのTip)

LastUpdate : 11/09/11

 PerlでCGIを作成する時に、メモしたことが書かれています。

☆ もくじ

  1. HTMLのformタグ内で使えるコントロールについて
  2. 兎にも角にも、HTMLを出力し、ブラウザで見ることのできる文章を表示する。
  3. 送信されたデータの処理(コントロールごとのvalueの切り出し&デコード
  4. 排他処理(似非
  5. locationについて(ページを移動させる)
  6. 改行記号を置換する。
  7. ブラウザから送信されたデータを、とりあえず、そのまま表示してみる(サンプルが長いです。
  8. ブラウザから送信されたデータをデコード・エンコードする(サンプルが長いです。
  9. perlからDBへのアクセス方法
  10. CGI.pmの使い方
  11. CGI::Sessionの使い方

HTMLのformタグ内で使えるコントロールについて

基本的なコントロールを列挙し、HTMLでの書き方をサンプルとして、載せます(これですべてではありません)。
また、タグの中で、nameとvalueという部分がありますが、この値をCGIで識別子・値として使います。

<form action="" method="post" target="_self">
formタグで囲まれた部分がactionで指定されたCGIに送信するデータの内容である。
action
   POSTかGETどちらかを指定する(メソッドの指定)。
target
   送信した結果のレスポンスが、どこに表示されるかを指定する。
   _blank : 新しいウインドウが開き、そこに結果が表示される。
   _top : フレームで画面が構成されている場合、フレームが解除され、そこに結果が表示される。
   _self : ボタンを押下したところの画面(これも画面がフレームで構成されていた場合の話)に結果が表示される。
   _parent : 画面が複数のフレームで構成されている場合、ボタンが押下された画面の親のウインドウに結果が表示される。

テキストボックス:

<input type="text" name="text_box" maxlength=12 size=50 value="デフォルトの値の指定。">

パスワード入力用テキストボックス:

<input type="password" name="password_text_box" maxlength=16 size=50 value="DefaultPassword">

チェックボックス:
チェックボックスだよーーん(横にテキストを書けばそれっぽくなるチェックボックス単体では文字列表示は無いみたい(?)。
<input type="checkbox" name="check_box1" checked value="check_box1_checked">

ラジオボタン(nameに同じ値を代入すれば同じグループとなる):
選択肢1
選択肢2
選択肢3
<input type="radio" name="radio1_group" value="radio1_checked1" checked>選択肢1
<input type="radio" name="radio1_group" value="radio1_checked2">選択肢2
<input type="radio" name="radio1_group" value="radio1_checked3">選択肢3

不可視コントロール(ユーザーからは見えない。任意の値をCGIに送るのに使う。):

<input type="hidden" name="hidden_ctrl" value="hidden_data">

コンボボックスボックス:

<select name="ComboBox1" size=1 title="サンプル用コンボボックス" align=left>
<option value="test1_selected">にゃーーーー。テスト1。
<option value="test2_selected">にゃーーーー。テスト2。
<option value="test3_selected">にゃーーーー。テスト3。
<option value="test4_selected">にゃーーーー。テスト4。
<option value="test5_selected">にゃーーーー。テスト5。

リストボックス(multipleオプションをつけると複数選択が可能になります。):

<select name="ListBox1" size=4 title="サンプル用リストボックス" align=left multiple> <option value="test1_selected">にゃーーーー。テスト1。
<option value="test2_selected">にゃーーーー。テスト2。
<option value="test3_selected">にゃーーーー。テスト3。
<option value="test4_selected">にゃーーーー。テスト4。
<option value="test5_selected">にゃーーーー。テスト5。

エディットボックス(複数行):

<textarea name="EditBoxM" title="サンプル用のエディットボックス(複数行)" cols=50 rows=5 wrap=soft> デフォルトの値。 </textarea>

フォームのボタン:


<input type="submit" value="送信。">
<input type="reset" value="リセット。"></form>
/formでフォームの終わりを示す。

兎にも角にも、HTMLを出力し、ブラウザで見ることのできる文章を表示する。

#最後に\n\nと改行を二回行うのは決まり事です。
#文法みたいなもんですw
#ヘッダ以外の部分の\nに特に意味はありません。
#HTMLを見たとき、見やすくするための改行です。
print "Content-type: text/html\n\n";    #ヘッダの出力。


print "<html>\n";
print " <header>\n";
print "         <title>CGIテスト用のページだよんw</title>";
print " </header>\n\n\n\n";

print "<body>";
print "<p>にゃんにゃんにゃん〜〜〜〜〜〜〜〜</p>";
print "</body>";

print "</html>";
実際動かしてみると、文字列がブラウザに表示されるはずです。
ヘッダの出力は重要です。HTML以外の出力に Content-type: text/plan というそのまま文章を表示するもののほか、いくつか種類があります。

送信されたデータの処理(コントロールごとのvalueの切り出し&デコード

 フォームから送信されてきたデータは、inputタグやtextareaタグで設定ししたnameという属性の値を識別子に、「 識別子=value 」という形になって送信されてきます。valueとは、そのコントロールに入力された値もしくはタグでvalue属性で指定した値のことです。

 コントロールが複数有る場合、たとえば、二つある場合、「 識別子=value&識別子=value 」という形で、「&」を区切りの印とし、データが送信されます。

 また、valueの値は場合により、エンコードされて送信されるデータもあります。正規表現で言う「 [^0-9A-Za-z*-.@_] 」にマッチする値は、「 %[0-9A-Fa-f][0-9A-Fa-f] 」という形式の値にエンコードされます。


 以下、送信されたデータを$sent_dataにみたてて、その値を、コントロールごとに分割・デコードを行う処理を書いてみます。サンプルの中に出てくる「あ」の文字コードは「0x82a0」です(シフトJIS)

use strict;

#送信されてきたデータ
#name1コントロールは「 abcdef 」という値を持ってる。
#name2コントロールは「 a b c d e f 」という値を持っている。
#name3コントロールは「 あ 」という値を持っている。
my $sent_data = 'name1=abcdef&name2=a+b+c+d+e+f&name3=%82%A0';


#name1=abcdef
#name2=a+b+c+d+e+f
#name3=%82%A0
#と、「 コントロール名前=値 」という形に分ける。
my @res = split(/&/,$sent_data);


#次に「 コントロール名前=値 」という値を
#コントロール名前と値に分割し、連想配列に代入する。
my %data=();

foreach(@res)
{
        my $name;
        my $value;
        ( $name,$value )= split(/=/,$_);        #文字列を=で分割。
        $data{ $name } = $value;        #連想配列に代入。
}

#現在の、それぞれの値を表示してみる。
print "Before:\n";
print 'name1 : ',$data{'name1'},"\n";
print 'name2 : ',$data{'name2'},"\n";
print 'name3 : ',$data{'name3'},"\n";

#valueをデコードする。
my @key_arr = keys(%data);

foreach( @key_arr )
{
        #スペース文字が+になってるので、それを直す。
        $data{$_} =~ tr/+/ /;
        #%xxになっているものを直す。
        $data{$_} =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("H2",$1)/eg;
}

#それぞれの値を表示してみる。
print "After:\n";
print 'name1 : ',$data{'name1'},"\n";
print 'name2 : ',$data{'name2'},"\n";
print 'name3 : ',$data{'name3'},"\n";
実行結果:

Before:
name1 : abcdef
name2 : a+b+c+d+e+f
name3 : %82%A0
After:
name1 : abcdef
name2 : a b c d e f
name3 : あ

排他処理(似非

 私の使っている環境ではflock関数が使えません。なので、排他制御を擬似的に実現するため、ディレクトリが有るか、無いかで判別しています。

 どこの環境でも普通に使える方法のはずです。しかし、flock関数などの、ロック専用の処理ではないので、排他制御処理としては甘い処理だと思います・・・。CGIで使う場合、シビアな処理には向かないと思います。

#実行時、ディレクトリの有る・無しで排他制御が
#できたらいいなぁ、と願う処理。
#flock関数を普通は使ってください。
#しかし、Win32のActivePerlでは使えないらしいです・・・。
#だからこの方式で書いてみます。

use strict;

#作成するディレクトリの名前
my $directory_name = 'lock_directory';
#試行回数
my $try_count = 4;
#使用中だった場合、Sleepしてる時間(秒数)。
my $sleep_time = 3;

while( 1 )
{
        if( mkdir($directory_name,0755) | $sleep_time-- <= 0 ){ last;   }
        print "wait...\n";
        sleep($sleep_time);
}
if( $sleep_time <= 0 )
{
        #待っても、ディレクトリが作成できない。
        #エラーとして処理を行う。
        print "error!\n";
        exit(0);
}

#なにかの処理の代わりにsleepを読んでいます。
#ここに、処理を記述します。
sleep(15);
print "ok!\n";


#処理が終わったので、ディレクトリを削除する。
rmdir($directory_name);

locationについて(ページを移動させる)

CGIにアクセスすると、Locationで指定されたページに移動します。
サンプルではCGIのファイルからの相対パスで一つ上のディレクトリのindex.htmlファイルに移動させています。

#!D:/tmp/f_program/activeperl/bin/perl
print "Location:../index.html\n\n";

改行記号を置換する。

textareaタグなどから入力された改行文字を、すべて、<br>に変換する処理です。

use strict;
my $str1 = "aaaaa\naaaaaa";
my $str2 = "aaaaa\r\naaaaaa";
my $str3 = "aaaaa\raaaaaa";

$str1 =~ s/\x0d\x0a|\x0d|\x0a/<br>/g;
$str2 =~ s/\x0d\x0a|\x0d|\x0a/<br>/g;
$str3 =~ s/\x0d\x0a|\x0d|\x0a/<br>/g;
print "str1:",$str1,"\n\nstr2:",$str2,"\n\nstr3:",$str3;
実行結果:

str1:aaaaa<br>aaaaaa

str2:aaaaa<br>aaaaaa

str3:aaaaa<br>aaaaaa

ブラウザから送信されたデータを、とりあえず、そのまま表示してみる。

エディットボックス二つと、hiddenのデータを一つを送信するフォームから、呼び出されるCGIです。
#!D:/tmp/f_program/activeperl/bin/perl

#受けたデータを、とりあえず、単純にすべて出力
#するためのサンプル。


#文法に制限を持たせる。
use strict;

#このスクリプトのpath
my $myself_name = '/~admin/cgi-bin/test.cgi';
#POSTでデータが送信される場合の最大サイズ
my $post_data_limit = 32*1024;
#送信されたデータを保持するバッファ
my $sent_data = '';
#postかgetかどちらでデータを受け取ったのかを表す文字列。
my $request_method = '';
#エディットボックス(text_box1)にいれる文字列
my $text_box1_str = 'あ';
#エディットボックス(text_box2)にいれる文字列
my $text_box2_str = 'ア';


#入力がPOSTがGETどうか調べ、それに応じた処理をする。
if( $ENV{ 'REQUEST_METHOD' } eq 'POST' )
{
        $request_method = 'post';
        $sent_data = &SentDataTypePOST();
}
elsif( $ENV{ 'REQUEST_METHOD' } eq 'GET' )
{
        $request_method = 'get';
        $sent_data = &SentDataTypeGET();
}
else
{
        &ProgramExit();
}


&OutputHTMLFromHeaderToBody();
&OutputInputForm();
print "\n\n",'Your sent data : ',$sent_data,"\n\n";
print '<br>';
print "request method : $request_method\n";

&OutPutHTMLFromEndBodyToEndHTML();
&ProgramExit();



#
#HTMLの最初から、bodyまでのHTMLソースコードを出力。
#
sub OutputHTMLFromHeaderToBody
{
        print "Content-type: text/html\n\n";    #ヘッダの出力。
        print <<HTML_START_TEXT;
<html>
        <header>
                <title>CGIテスト用のページだよんw</title>
        </header>

<body>
HTML_START_TEXT
        return 0;
}

#
#/bodyから/htmlまでのHTMLソースコードを出力。
#
sub OutPutHTMLFromEndBodyToEndHTML
{
        print <<HTML_END_TEXT;
</body>
</html>
HTML_END_TEXT
        return 0;
}

#
#入力用のformを出力。
#
sub OutputInputForm
{
        print '<form action="',$myself_name,'"',' method="POST"><br>',"\n";
        print '<input type="text" name="text_box1" maxlength=12 size=50 value="';
        print $text_box1_str;
        print '"><br>',"\n";
        print '<input type="text" name="text_box2" maxlength=12 size=50 value="';
        print $text_box2_str;
        print '"><br>',"\n";
        print <<INPUT_FORM_TEXT;

<input type="hidden" name="post_data1" value="data_send"><br>
<input type="submit" value="送信。">
</form>

INPUT_FORM_TEXT
        return 0;
}

#
#終了処理を行う。
#
sub ProgramExit
{
        exit(0);
}


#
#Getでデータが送られてきたときの処理。
#
sub SentDataTypeGET
{
        my $str = $ENV{'QUERY_STRING'};
        return $str;
}

#
#POSTでデータが送られてきたときの処理。
#
sub SentDataTypePOST
{
        my $post_data = '';
        my $len = $ENV{'CONTENT_LENGTH'};
        
        if( $len <= $post_data_limit )
        {
                read( STDIN,$post_data,$len );
        }
        return $post_data;
}
実行結果:

<html>
        <header>
                <title>CGIテスト用のページだよんw</title>
        </header>

<body>
<form action="/~admin/cgi-bin/test.cgi" method="POST"><br>
<input type="text" name="text_box1" maxlength=12 size=50 value="あ"><br>

<input type="text" name="text_box2" maxlength=12 size=50 value="ア"><br>
<input type="hidden" name="post_data1" value="data_send"><br>

<input type="submit" value="送信。">
</form>


Your sent data : text_box1=%82%A0&text_box2=%83A&post_data1=data_send

<br>request method : post
</body>

</html>

 このスクリプトを実行し、そのまま送信ボタンを押すと、こんな結果が出力されるはずです。
「 text_box1=%82%A0&text_box2=%83A&post_data1=data_send 」というデータがブラウザから送信されたことを示します。 このままでは、解釈不能なので、データをデコードしたりsplitしたりして、使えるようにしなければなりません。

 デコード方法として「 $str =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("H2",$1)/eg 」とやり、データをデコードします。
 しかし、ここではわかりやすくするため「 $str =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C",hex($1))/eg 」を使い考えます。
 サンプルはわざと「あ」と「ア」を入力しました。両者の値は「あ」は「 %82%A0 」で「ア」は「 %83A 」です。%xxで1バイトを表しているハズなのに、カタカナはなにかおかしい!と思うはずです。
しかし、これでちゃんと処理できます。シフトJISの「あ」の文字コードは「 0x82a0 」です。そして「ア」の文字コードは「 0x8341 」です。
例のとおり「あ」は「 0x82a0 」と%記号をぬけは、そのまま「あ」の文字コードと一致します。
「 s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C",hex($1))/eg 」の処理で「 %83A 」は、まず、 %83 の部分がマッチします。最初にマッチした値(正規表現では$1で最初にマッチした値を指す)はpack関数に渡されます(eオプションがついているため、式の評価が行われるため)。
そして、pack関数により"C"テンプレートを使うという設定なのでunsigned charの型のバイナリの構造体に0x83の値を入れます。それでまずは、一回目のマッチは終了します。
そして、次に、Aという文字から探索処理を行います。%が最初にきて・・・という探索なので、あまった「 A 」は処理されず、次の文字から再び探索が開始されます。
置換処理を行う処理により、0x83はバイナリデータとなったのですが「 A 」はそのままです。この「 A 」を数値として評価すると 0x41 です。そしてシフトJISの「ア」の文字コードは 0x8341 です。
なんと、「ア」になってしまいました!
・・・・・・・・・・という処理を行っているんだろうと、私は今のところ思ってます。違かったら、ごめんなさいtt。


ブラウザから送信されたデータをデコード・エンコードする。

 エディットボックス二つのデータを送信するフォームから、呼び出されるCGIです。エンコードされたデータをデコードして、それをまたエンコードして、またそれをデコードし、それを表示します。

#!D:/tmp/f_program/activeperl/bin/perl
#文法に制限を持たせる。
use strict;

#このスクリプトのpath
our $myself_name = '/~admin/cgi-bin/test.cgi';
#POSTでデータが送信される場合の最大サイズ
our $post_data_limit = 32*1024;
#送信されたデータを保持するバッファ
our $sent_data = '';
#postかgetかどちらでデータを受け取ったのかを表す文字列。
our $request_method = '';
#エディットボックス(text_box1)にいれる文字列
our $text_box1_str = 'あ';
#エディットボックス(text_box2)にいれる文字列
our $text_box2_str = 'ア';
#エディットボックス(text_box1)から入力された文字列をデコードした結果。
our $text_box1_decode_result = '';
#エディットボックス(text_box2)から入力された文字列をデコードした結果。
our $text_box2_decode_result = '';
#エディットボックス(text_box1)から入力された文字列を
#デコードした結果を再び、エンコードしてみた結果。
our $text_box1_encode_result = '';
#エディットボックス(text_box1)から入力された文字列を
#デコードした結果を再び、エンコードしてみた結果。
our $text_box2_encode_result = '';
#エディットボックス(text_box1)から入力された文字列を
#デコードした結果を再び、エンコードして、もう一回デコードした結果。
our $text_box1_decode2_result ='';
#エディットボックス(text_box1)から入力された文字列を
#デコードした結果を再び、エンコードして、もう一回デコードした結果。
our $text_box2_decode2_result ='';


#入力がPOSTがGETどうか調べ、それに応じた処理をする。
if( $ENV{ 'REQUEST_METHOD' } eq 'POST' )
{
        $request_method = 'post';
        &SentDataTypePOST();
}
elsif( $ENV{ 'REQUEST_METHOD' } eq 'GET' )
{
        $request_method = 'get';
        &SentDataTypeGET();
}
else
{
        &ProgramExit();
}


&OutputHTMLFromHeaderToBody();
&OutputInputForm();
print "\n\n",'Your sent data : ',$sent_data,"\n\n";
print '<br>';
print "request method : $request_method\n",'<br>';
print 'decode text_box1 : ',$text_box1_decode_result,"<br>\n";
print 'decode text_box2 : ',$text_box2_decode_result,"<br>\n";
print 'encode text_box1 : ',$text_box1_encode_result,"<br>\n";
print 'encode text_box2 : ',$text_box2_encode_result,"<br>\n";
print 'decode2 text_box1 : ',$text_box1_decode2_result,"<br>\n";
print 'decode2 text_box2 : ',$text_box2_decode2_result,"<br>\n";

&OutPutHTMLFromEndBodyToEndHTML();
&ProgramExit();



#
#HTMLの最初から、bodyまでのHTMLソースコードを出力。
#
sub OutputHTMLFromHeaderToBody
{
        print "Content-type: text/html\n\n";    #ヘッダの出力。
        print <<HTML_START_TEXT;
<html>
        <header>
                <title>CGIテスト用のページだよんw</title>
        </header>

<body>
HTML_START_TEXT
        return 0;
}

#
#/bodyから/htmlまでのHTMLソースコードを出力。
#
sub OutPutHTMLFromEndBodyToEndHTML
{
        print <<HTML_END_TEXT;
</body>
</html>
HTML_END_TEXT
        return 0;
}

#
#入力用のformを出力。
#
sub OutputInputForm
{
        print '<form action="',$myself_name,'"',' method="POST"><br>',"\n";
        print '<input type="text" name="text_box1" maxlength=12 size=50 value="';
        print $text_box1_str;
        print '"><br>',"\n";
        print '<input type="text" name="text_box2" maxlength=12 size=50 value="';
        print $text_box2_str;
        print '"><br>',"\n";
        print <<INPUT_FORM_TEXT;

<br>
<input type="submit" value="送信。">
</form>
INPUT_FORM_TEXT
        return 0;
}

#
#終了処理を行う。
#
sub ProgramExit
{
        exit(0);
}


#
#Getでデータが送られてきたときの処理。
#
sub SentDataTypeGET
{
        $sent_data = $ENV{'QUERY_STRING'};
        &DecodeEncode($sent_data);
}

#
#POSTでデータが送られてきたときの処理。
#
sub SentDataTypePOST
{
        my $len = $ENV{'CONTENT_LENGTH'};
        if( $len <= $post_data_limit )
        {
                read( STDIN,$sent_data,$len );
                &DecodeEncode($sent_data);
        }
}


#
#引数の値をデコードしグローバル変数にセットする。
#また、ためしにデコードされたものを、再びエンコードしてみる。
#それも、また別のグローバル変数にいれる。
#
#引数:
#       第一引数に、text_box1の値、第二引数にtext_box2の値を取る。
sub DecodeEncode
{
        #name=valueの形に区切る。
        my( $edit1,$edit2 ) = split( /&/,$_[0] );

        my $tmp;        
        #データのみを取得する。(name=valueをvalueの値のみにする。)
        ( $tmp,$edit1 ) = split( /=/,$edit1 );
        ( $tmp,$edit2 ) = split( /=/,$edit2 );
        
        #デコードを行う。
        $text_box1_decode_result = $edit1;
        $text_box2_decode_result = $edit2;
        $text_box1_decode_result =~ tr/ /+/;
        $text_box1_decode_result =~ s/%([0-9A-Fa-f][0-9A-Za-f])/pack('H2',$1)/eg;
        $text_box2_decode_result =~ tr/ /+/;
        $text_box2_decode_result =~ s/%([0-9A-Fa-f][0-9A-Za-f])/pack('H2',$1)/eg;
        
        #デコードしたものをエンコードしてみる。
        $text_box1_encode_result = $text_box1_decode_result;
        $text_box2_encode_result = $text_box2_decode_result;
        #英数字などの1バイト文字以外がいきたら、%をつけてunpackした値に変換。
        $text_box1_encode_result =~ s/([^\w])/'%'.unpack('H2',$1)/eg;
        $text_box2_encode_result =~ s/([^\w])/'%'.unpack('H2',$1)/eg;
        #半角スペースは'+'に変換されているので、それを直す。
        $text_box1_encode_result =~ tr/+/ /;
        $text_box2_encode_result =~ tr/+/ /;
        
        #さらにそれを、デコードしてみる。
        $text_box1_decode2_result = $text_box1_encode_result;
        $text_box2_decode2_result = $text_box2_encode_result;
        $text_box1_decode2_result =~ tr/ /+/;
        $text_box1_decode2_result =~ s/%([0-9A-Fa-f][0-9A-Za-f])/pack('H2',$1)/eg;
        $text_box2_decode2_result =~ tr/ /+/;
        $text_box2_decode2_result =~ s/%([0-9A-Fa-f][0-9A-Za-f])/pack('H2',$1)/eg;
}
実行結果:


<html>
        <header>
                <title>CGIテスト用のページだよんw</title>
        </header>
<body>
<form action="/~admin/cgi-bin/test.cgi" method="POST"><br>

<input type="text" name="text_box1" maxlength=12 size=50 value="あ"><br>
<input type="text" name="text_box2" maxlength=12 size=50 value="ア"><br>

<br>
<input type="submit" value="送信。">
</form>


Your sent data : text_box1=%82%A0&text_box2=%83A

<br>request method : post
<br>decode text_box1 : あ<br>

decode text_box2 : ア<br>
encode text_box1 : %82%a0<br>
encode text_box2 : %83A<br>
decode2 text_box1 : あ<br>
decode2 text_box2 : ア<br>
</body>

</html>



perlからDBへのアクセス方法

perlからDBにアクセスするにはDBIというものを使うらしい。
それの導入手順。
環境は、windows7 + ActivePerl。

ActivePerlをインストールすると、ppmというツールもインストールされる。コマンドプロンプトからppmと打つと以下のようなプログラムが立ち上がる。

ここでインストールするべきは2点。

・DBI → DB操作を行うインターフェイスを提供する
・DBD → DB毎のDBIの実装

DBDについては、使用しているDB毎に必要なものが違ってくる。今回、使用しているのはMySQLなので、DBD名前は「DBD-mysql」というものだ。

ActivePerlインストール時には、DBIはインストールされてるっぽい。なので、今回はDBD-mysqlのみインストールを行った。
虫眼鏡みたいなアイコンのあるエディットボックスで、一覧をフィルターできます。

こんな感じで、DBD-mysqlを右クリックして、そのメニューからインストールをうんたら・・っていうのを選択。

すると、「⇒」みたいな、緑のアイコンが押下できるようになるので、そこからインストール可能です。

CGI.pmの使い方

HTMLを自動で生成してくれたり、送信されたデータの受け渡しをやりやすくしてくれるライブラリです。
タグを出力してくれたりする機能については、使いやすいんだか、使いづらいんだかよくわからんwwwwww

(1)簡単なサンプル

とりあえず雰囲気を感じ取るために、サンプルを。タイトルタグが「サンプルです」、bodyタグ内に「にゃんにゃん」という文言が表示されるページを生成するサンプルです。

sample.cgi
#!/usr/bin/perl

my $encoding = 'Shift_JIS';
my $lang = 'ja-JP';


use CGI;
my $q = CGI->new;
print $q->header(-charset=>$encoding),
        $q->start_html(-title=>'サンプルです', 
                -lang=>$lang,
                -encoding=>$encoding),
        $q->h1('にゃんにゃん'),
        $q->end_html;
実行結果

(2)送信画面と受信したデータを書きだす画面のサンプル

データをPOSTする画面と、POSTされたデータを受け取り、それを画面に表示するプログラムをCGI.pmを使って書きます。
以下のような2画面を作成しました。
実行結果のキャプチャーと、ソースです。

CSSを読み込ませています。おまけとして、そのCSSもつけておきました。

データ入力画面(index.cgi)
データ入力結果画面(show.cgi)
index.cgi (データ入力画面)
#!"/usr/bin/perl"
use CGI;

my $encoding = 'Shift_JIS';
my $lang = 'ja-JP';
my $style_sheet_path = '../contents/css/common.css';
my $q = CGI->new;

# ヘッダーを出力(スタイルシートも出力させる)
print $q->header(-charset=>$encoding),
$q->start_html(-title=>'データ入力画面',
-lang=>$lang,
-encoding=>$encoding,
-style=>{-src=>$style_sheet_path});

# フォームタグを出力する(submitを押下されたら、show.cgiを呼び出す)
print $q->start_form(-method=>'POST', -action=>'show.cgi');


# 文言を表示
print $q->h4('すきなのを入力してね');
print $q->center($q->strong('以下のところへ好きなことを入力してください'));

print '注意事項';
print $q->ol(
$q->li('以下はほんの一例です').
$q->li('いろいろあるので、リファレンスは見ておいた方がいいです^^;')
);

# エディットボックスを表示
print 'エディットボックス : ';
print $q->textfield(-name=>'textInput', -default=>'にゃん', -size=>'20');
print $q->br, $q->br, "\n\n";

# パスワード入力エディットボックス
print 'パスワード : ';
print $q->password_field(-name=>'passwordInput', -size=>'20');
print $q->br, $q->br, "\n\n";

# テキストエリアを表示
print 'テキストエリア : ';
print $q->textarea(-name=>'message', -default=>'わんわん', -cols=>'40', -rows=>'5');
print $q->br, $q->br, "\n\n";

# コンボボックスを表示
print 'コンボボックス : ';
my @index_combo = (1, 2, 3);
my %label_combo = (1=>'ゆがみねぇな', 2=>'だらしねぇ', 3=>'仕方ないね');
print $q->popup_menu(-name=>'combo_box', -values=>[@index_combo], -default=>'100', -labels=>\%label_combo);
print $q->br, $q->br, "\n\n";


# リストボックスを表示
print 'リストボックス : ';
my @index_list = (1, 2, 3, 4 ,5);
my %label_list = (1=>'超スピード', 2=>'あん?焼き芋のパン?サンドウィッチ?', 3=>'いやぁ、スイマセーン', 4=>'見えるってのは辛いな、サム', 5=>'hey! come on!');
print $q->scrolling_list(-name=>'listbox', -size=>3, -values=>[@index_list], -default=>'1', -labels=>\%label_list, -multiple=>'false');
print $q->br, $q->br, "\n\n";

# チェックボックス(group)の表示
print 'チェックボックス(group) : ';
my @index_checkbox = (1, 2, 3, 4);
my %label_checkbox = (1=>'芋が無いと失礼だ', 2=>'それはそれでいいんか?', 3=>'じょっぱりだお〜', 4=>'承知');
print $q->checkbox_group(-name=>'checkbox_group', -values=>[@index_checkbox], -default=>['1', '2'], -labels=>\%label_checkbox);
print $q->br, $q->br, "\n\n";

# ラジオボタンの表示
print 'ラジオボタン : ';
my @index_radiobutton = (1, 2);
my %label_radiobutton = (1=>'森の妖精', 2=>'陸のクリオネ');
print $q->radio_group(-name=>'radiobutton', -values=>[@index_radiobutton], -default=>'1', -labels=>\%label_radiobutton);
print $q->br, $q->br, "\n\n";

# チェックボックス(単独)の表示
print 'チェックボックス(単独) : ';
print $q->checkbox(-name=>'checkbox_single', -value=>'imono_pan', -checked=>'1', -label=>'芋のパン');
print $q->br, $q->br, "\n\n";

# hiddenフィールド
print 'hiddenフィールド : (画面上には何も表示されません)';
print $q->hidden(-name=>'hidden_field_list', -default=>['saikyou', 'are you ok']);
print $q->hidden(-name=>'hidden_field', -default=>['saikyou']);
print $q->br, $q->br, "\n\n";

# 送信ボタン
print 'submitボタン : ';
print $q->submit(-value=>'送信');
print $q->br, $q->br, "\n\n";

# リセットボタン
print 'resetボタン : ';
print $q->reset(-value=>'リセット');
print $q->br, $q->br, "\n\n";

# フォームの終了タグを出力する
print $q->endform;

print $q->hr;

# リンクを張る
print 'リンク : ';
print $q->a({href=>'http://alctail.sakura.ne.jp'}, 'ホームページに戻る');
print $q->br, $q->br, "\n\n";

print $q->end_html;
show.cgi (入力データ表示画面)
#!"/usr/bin/perl"

use CGI;

my $q = CGI->new;
my $encoding = 'Shift_JIS';
my $lang = 'ja-JP';
my $style_sheet_path = '../contents/css/common.css';


# エディットボックスの値を受け取る
my $text_input = $q->param('textInput');

# パスワードの値を受け取る
my $password_input = $q->param('passwordInput');

# テキストエリアの値を受け取る
my $message = $q->param('message');

# コンボボックスの値を受け取る
my $combo_box = $q->param('combo_box');

# リストボックスの値を受け取る
my @list_box = $q->param('listbox');

# チェックボックスの値を受け取る
my @checkbox_group = $q->param('checkbox_group');

# ラジオボタンの値を受け取る
my $radiobutton = $q->param('radiobutton');

# チェックボックスの値を受け取る
my $checkbox_single = $q->param('checkbox_single');

# hiddenフィールドの値を受け取る
my @hiddenfield_list = $q->param('hidden_field_list');
my $hiddenfield = $q->param('hidden_field');



# 取得した値を画面へ表示する
# ヘッダーを出力(スタイルシートも出力させる)
print $q->header(-charset=>$encoding),
$q->start_html(-title=>'データ入力結果画面',
-lang=>$lang,
-encoding=>$encoding,
-style=>{-src=>$style_sheet_path});


print 'エディットボックス : '.$text_input;
print '<br>'."\n";
print 'パスワード : '.$password_input;
print '<br>'."\n";
print 'テキストエリア : '.$message;
print '<br>'."\n";
print 'コンボボックス : '.$combo_box;
print '<br>'."\n";
print 'リストボックス : '; foreach(@list_box){ print $_," "; };
print '<br>'."\n";
print 'チェックボックス(group) : '; foreach(@checkbox_group){ print $_," "; };
print '<br>'."\n";
print 'ラジオボタン : '.$radiobutton;
print '<br>'."\n";
print 'チェックボックス(単独) : '.$checkbox_single;
print '<br>'."\n";
print 'hiddenフィールド : '; foreach(@hiddenfield_list){ print $_," "; };
print '<br>'."\n";
print 'hiddenフィールド : '.$hiddenfield;
print '<br>'."\n";


# 送信したパラメータを取得することも可能です。
print '<br><br>パラメータの一覧を取得し、表示します<br>', "\n";
my @key_list = $q->param;
foreach(@key_list) {
print 'param name : ', $_;
print '<br>', "\n";
}

print $q->end_html;
common.css
body
{
background-image: url("../img/back.png");
background-repeat: repeat-x repeat-y;

}

a:hover
{
background-color: #E0D0F0;
}

h4
{
border-bottom: solid 2px #bbccff;
border-left: solid 1em #bbccff;
}

CGI::Sessionの使い方

説明書としては、このあたりを見ればよろしいかと(さくらインターネットにインストールされているCGI-Sessionが、4.40らしいので、そのバージョンのページを張っておく)

http://search.cpan.org/~markstos/CGI-Session-4.40/

セッションのデータ保管先として、ファイルか、MySQLが選べる。
具体的な使い方を以下に示す。

セッションデータのストレージとしてファイルを選択した場合