list.txtは、番号、名前、性別がコンマで区切られたCSVファイルである。 list.txtの内容を読み取って、各行の項目の値をタブで区切って、webページで表示するCGIスクリプトshowlist.cgiをサブルーチン化して、show_list.cgiを作成してみた。
#! /usr/bin/perl
my $top_page = "index.html";
my $filename = "list.txt";
my @data =();
read_records();
show_list();
exit;
################### subroutines ##################
sub show_list
{
print "Content-Type: text/html;charset=Shift_JIS;\n\n";
print "<html><head>\n";
print "<title>CGI sample</title>\n";
print "<link href=\"homework.css\" rel=\"stylesheet\" type=\"text/css\">\n";
print "</head>\n<body>\n";
print "<h2>リストの表\示</h2>\n";
print "<table>";
foreach (@data){
print "<tr><td>$_->{number}</td><td>$_->{name}</td><td>$_->{gender}</td></tr>\n";
}
print "</table>";
print "</body></html>\n";
}
sub read_records
{
my( $number, $name, $gender);
# 読み取りモードでファイルを開く
open(IN, "<$filename") || &error("Cannot read $filename: $!");
while(<IN>){
chomp;
( $number, $name, $gender) = split(/,/, $_);
# 無名ハッシュを配列にする
push @data,
{
'number'=>$number,
'name'=>$name,
'gender' =>$gender
};
}
# ファイルを閉じる
close(IN);
}
# エラー表示
sub error
{
print "Content-Type: text/html\n\n";
print <<"---EOF---";
<html><head><title>Information</title></head>
<body>
<span sylte="color: red;"> $_[0]</span>
<form method="GET" action="$top_page">
<input type=SUBMIT value="最初のページに戻る">
</form>
</body></html>
---EOF---
exit;
}
show_list.cgiを改造して、新しいデータを追加できるようにしたい。そのために、新しいデータを追加するための入力フォームを、edit_record.htmlという名前のHTMLファイルとして作成しておこう。
フォームのパラメータは以下の通りとした:
<html> <head> <title>レコードの編集</title> </head> <body> <form method="POST" action="add_record.cgi" > 番号:<input type="text" name="NUMBER"><br> 名前:<input type="text" name="NAME">(空欄にすると、そのデータは削除されます)<br> 性別: <label><input type="radio" name="GENDER" value="男">男性 </label> <label><input type="radio" name="GENDER" value="女">女性</label> <br> <input type="submit" value="送信"> </form> </body> </html>
show_list.cgiを改造してadd_record.cgiという名前で、新しいデータの入力やデータの削除ができるようしよう。このCGIスクリプトは、上で作成したedit_record.htmlから呼び出すものとする。
#! /usr/bin/perl
my $top_page = "index.html";
my $filename = "list.txt";
my %param;
my @data;
%param = get_param();
if( $param{NUMBER} ne "" || $param{NAME} ne "" ){
@data =(); # @dataを初期化
read_records();
update_data($param{NUMBER}, $param{NAME}, $param{GENDER});
}
@data =(); # @dataを初期化
read_records();
show_list();
exit;
################### subroutines ##################
sub update_data
{
my $Number =$_[0];
$Number =~ s/\s+//g; # 空白は削除
$Number =~ s/\D+//g; # 数字以外は削除
my $Name = $_[1];
my $Gender = $_[2];
my $flag = 0;
foreach (@data){
if( $_->{number} eq $Number ){
$flag = 1;
$_->{name} = $Name;
$_->{gender} = $Gender;
if( $Name eq "" ){
delete $_->{number};
delete $_->{name};
delete $_->{gender};
}
}
}
if($flag == 0 && $Number ne "" && $Name ne "" && $Gender ne ""){
push @data, { 'number'=>$Number, 'name'=>$Name, 'gender' =>$Gender };
}
# 書き込みモードでファイルを開く
open(OUT, ">$filename") || &error("Cannot open $filename: $!");
foreach (@data){
if($_->{number} eq ""){ next;} # データがNULLの場合は書き出さない。
print OUT "$_->{number},$_->{name},$_->{gender}\n";
}
# ファイルを閉じる
close(OUT);
}
sub read_records
{
my( $number, $name, $gender);
# 読み取りモードでファイルを開く
open(IN, "<$filename") || &error("Cannot read $filename: $!");
while(<IN>){
chomp;
( $number, $name, $gender) = split(/,/, $_);
# 無名ハッシュを配列にする
push @data,
{
'number'=>$number,
'name'=>$name,
'gender' =>$gender
};
}
# ファイルを閉じる
close(IN);
}
sub show_list
{
print "Content-Type: text/html;charset=Shift_JIS;\n\n";
print "<html><head>\n";
print "<title>CGI sample</title>\n";
print "<link href=\"homework.css\" rel=\"stylesheet\" type=\"text/css\">\n";
print "</head>\n<body>\n";
print "<h2>リストの表\示</h2>\n";
print "<table>";
foreach (@data){
print "<tr><td>$_->{number}</td><td>$_->{name}</td><td>$_->{gender}</td></tr>\n";
}
print "</table>";
print "<a href=\"edit_record.html\">入力フォーム</a>";
print "</body></html>\n";
}
# 入力データの取得
sub get_param
{
my($query, $key, $value, %param);
if($ENV{REQUEST_METHOD} eq "GET"){
$query = $ENV{QUERY_STRING};
}else{
read(STDIN, $query, $ENV{CONTENT_LENGTH});
}
foreach(split(/&/, $query)){
($key, $value) = split(/=/, $_);
$value =~ s/\+/ /g;
$value =~ s/%([\da-f][\da-f])/pack("C", hex($1))/egi;
## &jcode'convert($value, 'euc');
$value =~ s/\r//g;
$param{$key} = $value;
}
return %param;
}
# エラー表示
sub error
{
print "Content-Type: text/html\n\n";
print <<"---EOF---";
<html><head><title>Information</title></head>
<body>
<span sylte="color: red;"> $_[0]</span>
<form method="GET" action="$top_page">
<input type=SUBMIT value="最初のページに戻る">
</form>
</body></html>
---EOF---
exit;
}
add_record.cgiのshow_listサブルーチンをヒアドキュメントという方法で書き換える。ヒアドキュメントは、print関数でHTMLのソースを出力するとき、ラベルで指定した範囲までを出力するという書き方をしたもので、HTMLのソースコードが読みやすくなるという利点がある。
[add_record.cgi]
#! /usr/bin/perl
my $top_page = "index.html";
my $filename = "list.txt";
my %param;
my @data;
%param = get_param();
if( $param{NUMBER} ne "" || $param{NAME} ne "" ){
@data =(); # @dataを初期化
read_records();
update_data($param{NUMBER}, $param{NAME}, $param{GENDER});
}
@data =(); # @dataを初期化
read_records();
show_list();
exit;
################### subroutines ##################
sub update_data
{
my $Number =$_[0];
$Number =~ s/\s+//g; # 空白は削除
$Number =~ s/\D+//g; # 数字以外は削除
my $Name = $_[1];
my $Gender = $_[2];
my $flag = 0;
foreach (@data){
if( $_->{number} eq $Number ){
$flag = 1;
$_->{name} = $Name;
$_->{gender} = $Gender;
if( $Name eq "" ){
delete $_->{number};
delete $_->{name};
delete $_->{gender};
}
}
}
if($flag == 0 && $Number ne "" && $Name ne "" && $Gender ne ""){
push @data, { 'number'=>$Number, 'name'=>$Name, 'gender' =>$Gender };
}
# 書き込みモードでファイルを開く
open(OUT, ">$filename") || &error("Cannot open $filename: $!");
foreach (@data){
if($_->{number} eq ""){ next;} # データがNULLの場合は書き出さない。
print OUT "$_->{number},$_->{name},$_->{gender}\n";
}
# ファイルを閉じる
close(OUT);
}
sub read_records
{
my( $number, $name, $gender);
# 読み取りモードでファイルを開く
open(IN, "<$filename") || &error("Cannot read $filename: $!");
while(<IN>){
chomp;
( $number, $name, $gender) = split(/,/, $_);
# 無名ハッシュを配列にする
push @data,
{
'number'=>$number,
'name'=>$name,
'gender' =>$gender
};
}
# ファイルを閉じる
close(IN);
}
sub show_list
{
print "Content-Type: text/html;charset=Shift_JIS;\n\n";
print <<"_HTML_";
<html>
<head>
<title>CGI sample</title>
<link href="homework.css" rel="stylesheet" type="text/css">
</head>
<body>
<h2>リストの表\示</h2>
<table>
_HTML_
foreach (@data){
print "<tr><td>$_->{number}</td><td>$_->{name}</td><td>$_->{gender}</td></tr>\n";
}
print <<"_HTML_";
</table>
<a href="edit_record.html">入力フォーム</a>
</body>
</html>
_HTML_
}
# 入力データの取得
sub get_param
{
my($query, $key, $value, %param);
if($ENV{REQUEST_METHOD} eq "GET"){
$query = $ENV{QUERY_STRING};
}else{
read(STDIN, $query, $ENV{CONTENT_LENGTH});
}
foreach(split(/&/, $query)){
($key, $value) = split(/=/, $_);
$value =~ s/\+/ /g;
$value =~ s/%([\da-f][\da-f])/pack("C", hex($1))/egi;
## &jcode'convert($value, 'euc');
$value =~ s/\r//g;
$param{$key} = $value;
}
return %param;
}
# エラー表示
sub error
{
print "Content-Type: text/html\n\n";
print <<"---EOF---";
<html><head><title>Information</title></head>
<body>
<span sylte="color: red;"> $_[0]</span>
<form method="GET" action="$top_page">
<input type=SUBMIT value="最初のページに戻る">
</form>
</body></html>
---EOF---
exit;
}