§8 フォームからの入力に応答 - エラーチェックあり -


前章で作成した応募CGIに、正解者の証明であるクッキーデーターと入力チェックを追加して完成させる。


▼エラーチェックありのサンプル

#!/usr/local/bin/perl
use strict;
use CGI;
use Jcode;

# CGIモジュールを誕生させる
my $query = new CGI;

# クッキーの状態を見て、正解者か判定する
my $seikai = $query->cookie(-name=>'panda_quiz');    #…(1)
if ($seikai ne 'seikai'){
  fuseikai_error_page();
  exit;
}

# フォームからのデーターを取り出す
my $name = $query->param('name');
my $address = $query->param('address');
my $age = $query->param('age');
my $email = $query->param('email');

# EUC文字コードに統一する
$name = new Jcode($name)->euc;
$address = new Jcode($address)->euc;

# エラーメッセージをセットする配列
my @message;

# 名前のチェック
unless ($name){
  push(@message, '名前が未入力です。');    #…(2)
}

# 住所のチェック
unless ($address){
  push(@message, '住所が未入力です。');
}

# 年齢のチェック
if ($age){
  if ($age =~ /\D/){    #…(3)
    push(@message, '年齢は半角数字で入力してください。');
    }
  }
  else{
  push(@message, '年齢が未入力です。');
}

# メールアドレスのチェック
if ($email){
  if ($email =~ /[^0-9a-zA-Z@._\-]/){    #…(4)
    push(@message, '年齢は半角英数字と記号(@._-)で入力してください。');
    }
  }
  else{
  push(@message, 'メールアドレスが未入力です。');
}

# エラーがあればエラーページを返し、終了
if (@message > 0){    #…(5)
  input_error_page(@message);
  exit;
}

# 応募データーを保存
if (open (FILE, ">>oubo.txt")){
  my $ouboData;
  $ouboData = join(',', $name, $address, $age, $email);
  print FILE "$ouboData\n";
  close FILE;
  }
  else {
  die ("オープンエラー");
}

# Webページを返す
print "Content-Type: text/html\n\n";
print <<"END_HTML";
<html>
<head>
<title>パンダクイズ</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" cellpadding="10" cellspacing="0">
  <tr>
  <td><img src="img/panda2.gif" width="111" height="150"></td>
  <td>$nameさん、ご応募ありがとうございました。</td>
  </tr>
</table>
</body>
</html>
END_HTML


#--------------------------------------------------
# 正解者でないページを返す
#--------------------------------------------------
sub fuseikai_error_page {
print "Content-Type: text/html\n\n";
print "<html>\n";
print "<head>\n";
print "<title>パンダクイズ エラー</title>\n";
print "</head>\n";
print "<body bgcolor=\"#FFFFFF\">\n";
print "あなたは正解していません。<br>\n";
print "</body>\n";
print "</html>\n"
}

#--------------------------------------------------
# エラーページを返す
#--------------------------------------------------
sub input_error_page {
my @message = @_;    #…(6)

my $text;

print "Content-Type: text/html\n\n";
print "<html>\n";
print "<head>\n";
print "<title>パンダクイズ エラー</title>\n";
print "</head>\n";
print "<body bgcolor=\"#FFFFFF\">\n";
print "<h2>入力エラー</h2>\n";
print "ブラウザの戻るボタンで戻って正しく入力してください。<br>\n";
foreach $text (@message){
print "$text<br>\n";
}
print "</body>\n";
print "</html>\n"
}


■クッキーからデーターを取得 ・・・(1)
my $seikai = $query->cookie(-name=>'panda_quiz');
cookieの命令にvalueを指定せずにnameだけを指定すると-nameに対応するデーターを取り出せる。-nameには、クッキーを保存したときの名前を指定する。

■エラーメッセージを配列に持たせる ・・・(2)
push(@message, '名前が未入力です。');
複数のエラーメッセージを一度に表示させるため、一旦配列に代入して保存する。 エラーメッセージの文字列を配列の最後にセットしたいので、pushという命令を使う。

■正規表現
正規表現とは、文字列の中にパターンで指定する文字が含まれているかどうか確かめる方法。 パターンを表す文字、記号は/と/で囲んで表す。
▼正規表現の主な記号
記号 意   味
. 改行コードを除く任意の1文字。
* 直前の文字(パターン)の0回以上の繰り返し。
+ 直前の文字(パターン)の1回以上の繰り返し。
? 直前の文字(パターン)が0回または1回現れる。
^ 文字列の先頭。
$ 文字列の末尾。
\ .*+?^$などパターンの記号として決まっている文字を使う場合に左隣につける。
▼サンプル
/panda/ 「・・・panda・・・」の文字列にマッチする。
/p.nda/ .は任意の1文字にマッチするので「panda」や「pbnda」などの文字列にマッチする。
/pa*nda/ *は直前の文字の0回以上の繰り返しにマッチするので、「pnda」や「panda」や「paaanda」の文字列にマッチする。
/pa+nda/ *は直前の文字の1回以上の繰り返しにマッチするので、「panda」や「paaanda」の文字列にマッチする。
/pa?nda/ ?は直前の文字が0回か1回現れる場合にマッチするので、「pnda」や「panda」の文字列にマッチする。
/^panda/ 行の先頭から始まる「panda」の文字列にマッチする。「pandaxyz」などにマッチする。
/^panda/ 行の末尾にある「panda」の文字列にマッチする。「xyzpanda」などにマッチする。

■正規表現で数字チェック ・・・(3)
if ($age =~ /\D/){・・・}
数字かどうかのチェックは正規表現で行える。=~ は変数に入っている文字や数値を正規表現でチェックし、 存在すれば正しい(真)、存在しなければ誤り(偽)の結果を返す記号。\Dは正規表現で数字以外の文字を表す特別な記号。
▼正規表現の主な特別な記号
記号 意   味
\n 改行コード。
\t タブコード。
\d 0〜9の数字。
\D 0〜9の数字以外。
\w 単語を構成する文字。a〜zとA〜Zと0〜9と_(アンダーバー)。
\W 単語を構成する文字以外。a〜zとA〜Zと0〜9と_(アンダーバー)以外。

■正規表現で英数字チェック ・・・(4)
if ($age =~ /[^0-9a-zA-Z@._\-]/){・・・}
[]はこの中に入っている文字のどれかという意味を表す正規表現の記号。 その中の先頭に^の記号をつければ[]の中にある文字以外の意味になる。 -は範囲を表す記号で0-9とは0〜9の文字を表す。 -とマッチさせたい場合は正規表現の記号なので左側に\をつける。

■配列のデーター数をチェック ・・・(5)
if (@message > 0){・・・}
先頭に@のついた変数は配列を表すが、数字と比較する場合は配列に代入している文字列の個数を表す。(棚に入っている箱の数を表す)

■引数の受け取り ・・・(6)
my @message = @_;
自作した関数でも引数を受け取ることができる。引数の値は@_の特別な変数に入っているので、関数の先頭で別の変数に取り出す。




戻る メニューへ 次へ