解説 11月(4)

今回の学習項目です。


フォーム部品の使い方

これまでに作成してきたWebページでは、フォームを用いてブラウザからCGIプログラムに情報を渡すときに、テキスト入力フィールドやパスワード入力フィールド、隠しフィールドや実行ボタンなどのフォーム部品を使用してきました。
フォーム部品には、この他にもいくつかの種類が用意されています。 部品によってタグの書き方や使い方が異なりますので、それらの違いを学んでおきましょう。

課題1

課題1-1

課題1-1では、次のようなプロフィール入力用フォームを表示するHTMLファイルと、送信されたプロフィール情報を受け取って表示するCGIプログラムを作成します。

プロフィール入力ページ

プロフィール入力用フォームでは、ラジオボタンやチェックボックス、セレクトボックスやテキストエリアなど、これまでとは異なるフォーム部品を使用しています。 部品ごとにタグの書き方も異なりますので、一つ一つ確認しながら、プロフィール入力ページを作成していくことにしましょう。

課題1-1-0

新しいフォーム部品の使い方を学ぶ前に、これまでに使用してきたフォーム部品の復習と、値を受け取って表示するCGIプログラムの用意をしておきましょう。

プロフィール入力ページ(テキスト入力フィールドと実行ボタンを使用)

上のようなプロフィール入力ページを表示するHTMLファイルを作成しなさい。 名前と性別と趣味の情報を送信するために、テキスト入力フィールドと実行ボタンを使用します。
また、送信された情報を受け取り、確認のためにページに表示するCGIプログラムも作成しなさい。

[<form>タグの書き方]

<form>タグはCGIプログラムに値を渡すために使用されるHTMLのタグです。 次のように書きます。

<form method="GET" action="ファイル名またはURL">
  フォーム部品
  フォーム部品
  フォーム部品
</form>

<form>タグには送信方法(GETなど)と送信先を指定します。 送信する情報の内容は、<form>タグの間に配置されるフォーム部品によって決まります。

[テキスト入力フィールドのタグの書き方]

テキスト入力フィールドは、1行分の文字列を入力することのできる、最も一般的なフォーム部品です。 次のように書きます。

  <input type="text" name="パラメータ名1">
  <input type="text" name="パラメータ名2" size="横幅の数値">
  <input type="text" name="パラメータ名3" value="初期値">

実際に使用する際には、<form>タグの間に<input>タグを書く必要があります。 送信時には、ユーザーによって入力された文字列に、name属性で指定されたパラメータ名が付けられます。

横幅を指定したいときはsize属性に数値を指定します。 初期値を設定したいときはvalue属性に値を指定します。 size属性やvalue属性は省略することができます。

[実行ボタンのタグの書き方]

実行ボタンは、<form>タグに指定された送信先のCGIプログラムに情報を送信し、CGIプログラムを実行するためのフォーム部品です。 次のように書きます。

  <input type="submit" value="ボタンに表示される文字">

他のフォーム部品と同じように、<form>タグの間に<input>タグを書く必要があります。 このボタンがクリックされると、<form>タグの間に配置された他のフォーム部品に入力された情報が送信されます。

課題1-1-1 ラジオボタン

ラジオボタンは、あらかじめ用意した選択肢の中からどれか一つを選択させるときに使用するフォーム部品です。

プロフィール入力ページ(ラジオボタンを使用)

ラジオボタンを使用して、用意された選択肢の中から性別と趣味を選択できるようにしなさい。 選択した値が正しく送信され、確認ページに表示されることも確かめなさい。

[ラジオボタンのタグの書き方]

ラジオボタンを使用するときは次のように書きます。

  <input type="radio" name="パラメータ名1" value="値1">文字1
  <input type="radio" name="パラメータ名1" value="値2">文字2
  <input type="radio" name="パラメータ名1" value="値3">文字3

他のフォーム部品と同じように、<form>タグの間に<input>タグを書く必要があります。 ユーザーは同じパラメータ名のラジオボタンの中から、どれか一つだけを選ぶことができます。 送信時には、value属性に指定された値に、name属性で指定されたパラメータ名が付けられます。 ただし、実際に送信されるのは、そのとき選択されているボタンの値だけです。

課題1-1-2 チェックボックス

チェックボックスは、選択肢の中から複数の回答を選ばせるときに使用するフォーム部品です。

プロフィール入力ページ(チェックボックスを使用)

チェックボックスを使用して、趣味を複数回答できるようにしなさい。 また、受け取った趣味の値を全部表示できるようにCGIプログラムを書き換えなさい。

[チェックボックスのタグの書き方]

チェックボックスを使用するときは次のように書きます。

  <input type="checkbox" name="パラメータ名1" value="値1">文字1
  <input type="checkbox" name="パラメータ名1" value="値2">文字2
  <input type="checkbox" name="パラメータ名1" value="値3">文字3

他のフォーム部品と同じように、<form>タグの間に<input>タグを書く必要があります。 送信時には、value属性に指定された値に、name属性で指定されたパラメータ名が付けられます。 選択されている全てのチェックボックスの値が送信されますので、同じパラメータ名で複数の値が送信されることになります。 送信後のURLのパラメータ部分を確認してみましょう。

http:// ... /○○○.cgi?パラメータ名1=値1&パラメータ名1=値2&パラメータ名1=値3&...

このようなパラメータの値をCGIプログラムで受け取る方法は、次の「同じパラメータ名で渡される複数の値をCGIで受け取るには」を参照してください。

[同じパラメータ名で渡される複数の値をCGIで受け取るには]

CGIプログラムで、同じパラメータ名の値を複数受け取るときは、次のようにCGIクラスのparamsメソッドを使用します。

require "cgi"    #CGIクラスを読み込む。

cgi = CGI.new                        #CGIクラスのインスタンスオブジェクトを生成。
変数1 = cgi.params["パラメータ名1"]  #同じパラメータ名で送信された複数の値を取得。

受け取った複数の値は、次のように配列に格納された状態で取得することができます。

["値1", "値2", "値3"]

[ヒント]

趣味の回答を表示するときは、"映画 音楽 スポーツ" というように、半角スペースを間に挟みつつ、送信された趣味の値を連結するようにします。文字列と文字列の連結には次のように + を使用しました。

ary = ["映画", "音楽", ...]

str = ary[0] + " " + ary[1] + " " + ...

趣味の項目は複数回答できますので、forなどの繰り返しを使うとよいでしょう。次のような数の足し込みを行うプログラムが参考になるかもしれません。

ary = [10, 20, 30, 40]

goukei = 0
for x in ary
  goukei = goukei + x
end

p goukei

今回は文字列を繰り返し連結しますので、最初は 0 ではなく、空の文字列 "" を用意しておくとよいでしょう。

ary = ["映画", "音楽", ...]

syumi = ""
for x in ary
  ...

[オフラインでの実行時に同じパラメータ名で複数の値を入力するには]

3通りの方法がありますが、一番上の方法ならパラメータがコマンドの履歴として残りますので、デバッグ中には便利です。

[h209xxx@ls01 h209xxx]% ./profile2.cgi name=中京太郎 hobby=映画 hobby=音楽
[h209xxx@ls01 h209xxx]% ./profile2.cgi
Content-type: text/html; charset=euc-jp

(offline mode: enter name=value pairs on standard input)
name=中京太郎
hobby=映画
hobby=音楽
#Ctrl + d を押して実行。

[h209xxx@ls01 h209xxx]% ./profile2.cgi
Content-type: text/html; charset=euc-jp

(offline mode: enter name=value pairs on standard input)
name=中京太郎&hobby=映画&hobby=音楽
#Ctrl + d を押して実行。

課題1-1-3 セレクトボックス

セレクトボックスは、ラジオボタンと同じように、あらかじめ用意された選択肢の中からどれか一つを選択させるときに使用するフォーム部品です。 普段は選択肢が折りたたまれているため、ラジオボタンよりも少ないスペースで表示することができます。

プロフィール入力ページ(セレクトボックスを使用)

セレクトボックスを使用して、学年を選択できるようにしなさい。 また、受け取った学年の値を確認ページに表示できるようにCGIプログラムを書き換えなさい。

[セレクトボックスのタグの書き方]

セレクトボックスの書き方は、これまでのフォーム部品とは少々異なります。 <input>タグではなく、<select>タグと<option>タグを使用します。 次のように書きます。

  <select name="パラメータ名">
    <option value="値1">文字1</option>
    <option value="値2">文字2</option>
    <option value="値3">文字3</option>
  </select>

<select>タグは<input>タグと同じように、<form>タグの間に書く必要があります。 <select>タグの間には、複数の<option>タグを配置していきます。 <option>タグは、セレクトボックスの一つ一つの選択肢になり、送信時には選択された選択肢の値だけが送信されます。 送信される値には、<select>タグのname属性に指定されたパラメータ名が付けられます。

課題1-1-4 テキストエリア

テキストエリアは、複数行入力可能な入力フィールドを表示するときに使用するフォーム部品です。

プロフィール入力ページ(テキストエリアを使用)

テキストエリアを使用して、コメントを入力できるようにしなさい。 また、受け取ったコメントを確認ページに表示できるようにCGIプログラムを書き換えなさい。

[テキストエリアのタグの書き方]

テキストエリアを使用するときは次のように書きます。

  <textarea name="パラメータ名" cols="横幅の数値" rows="縦幅の数値"></textarea>

<textarea>タグは<input>タグと同じように、<form>タグの間に書く必要があります。 送信時には、ユーザーによって入力された文字列に、name属性で指定されたパラメータ名が付けられます。

cols属性やrows属性は省略することができます。 初期値を設定したいときは、<textarea>タグの間に文字を書きます。

  <textarea name="パラメータ名">初期値</textarea>

テキストエリアを使用する場合は、ユーザーによって大量の文字列が入力されることが予想されますので、<form>タグのmethod属性にPOSTを指定しておくとよいでしょう。

<form method="POST" action="ファイル名またはURL">
  フォーム部品
  <textarea name="パラメータ名" cols="横幅の数値" rows="縦幅の数値"></textarea>
  フォーム部品
</form>

POSTについては、次の「GETとPOSTの違い」を参照してください。 また、改行コードの扱いに関して、「受け取ったコメントを改行して表示するには」も参照しておいてください。

[GETとPOSTの違い]

<form>タグのmethod属性にGETを指定して送信する場合は、送信先のURLにパラメータとして情報が付け加えられ、送信されました。 しかし、URLの長さには制限のある場合がありますので、長いパラメータを付加して送信すると、途中で途切れてしまうことがあります。 GETを指定してURLのパラメータとして情報を送信するのは、例えばE-mailで言うと、本文ではなく、宛先や件名などの情報を送信しているようなものなのです。

これに対して、POSTを指定して情報を送信する場合は、URLの一部ではなく、独立した本文としてデータが扱われます。 そのため、GETのときのようにデータの長さを気にする必要はありません。 テキストエリアを使用する場合など、大量のデータが送信されることが予想されるときには、<form>タグのmethod属性にPOSTを指定して情報を送信するようにしましょう。

また、POSTの場合、送信後のURLにパラメータの情報が付加されませんので、パスワードなど、人目に触れてはいけない情報を送信する際にも、POSTが使用されることが少なくありません。

[受け取ったコメントを改行して表示するには]

テキストエリアでは文章を途中で改行することができますので、送信される文字列には改行コードが含まれている可能性があります。 Webページに文章を改行して表示するときは改行タグを使う必要がありますので、ユーザーの入力した通りに文章を表示するためには、文字列中の改行コードを改行タグに置き換えなければいけません。

次のようにStringクラスのgsubメソッドを使用すれば、文字列に含まれるすべての改行コードを改行タグに置き換えることができます。 (Windows環境では、\nではなく、\r\nという改行コードが使用されます。)

comment = "あいうえお\r\nかきくけこ\r\nさしすせそ\r\n"

replaced_comment = comment.gsub("\r\n", "<br>")  #文字列に含まれる改行コードを改行タグに置換。

p comment
p replaced_comment
"あいうえお\r\nかきくけこ\r\nさしすせそ\r\n"
"あいうえお<br>かきくけこ<br>さしすせそ<br>"

課題1-1-5 隠しフィールド

隠しフィールドは、他のフォーム部品と同じようにCGIプログラムに値を渡すために使用される、姿の見えないフォーム部品です。 他のフォーム部品のように、ユーザーにWebページ上で値を入力させるのではなく、あらかじめ設定した値がそのまま送信されます。 ユーザーにより一度入力された情報を、ユーザーに意識させることなく再送するときなどに使用します。

プロフィール入力ページ(確認ページで隠しフィールドを使用)

上のプロフィール入力ページに入力した情報は、「確認」ボタンをクリックすることによって確認ページへ送信され、さらに、「登録」ボタンをクリックすることによって、登録ページへ送信されます。 確認ページでは実行ボタン以外のフォーム部品を使用していないように見えますが、登録ページにプロフィールの情報が送信されているのはなぜでしょう? 実は確認ページでは、目には見えない隠しフィールドが使用されているのです。

[隠しフィールドのタグの書き方]

隠しフィールドを使用するときは次のように書きます。

  <input type="hidden" name="パラメータ名1" value="値1">

  <input type="hidden" name="パラメータ名2" value="値2">

  <input type="hidden" name="パラメータ名3" value="値3">
  <input type="hidden" name="パラメータ名3" value="値4">
  <input type="hidden" name="パラメータ名3" value="値5">

他のフォーム部品と同じように、<form>タグの間に<input>タグを書く必要があります。 送信時には、value属性に指定された値に、name属性で指定されたパラメータ名が付けられます。

[隠しフィールドの使われている場所は?]

プロフィール確認ページでは、プロフィール入力ページから送られた名前や性別などの情報を表示するだけでなく、プロフィール登録ページのCGIプログラムへ送らなくてはいけません。 そうしなければ、登録ページのCGIプログラムで、どのような情報を登録すればよいかわからなくなってしまいます。

そこで、確認ページでは、隠しフィールドを使用して、受け取った名前や性別などの情報を、登録ページへ送信するようにしています。 Webページ上には表示されていませんが、Webページのソース(HTML文書)を見れば、「登録」という実行ボタンの上部に、隠しフィールドのタグが書かれていることがわかるはずです。 ソースを見ると、隠しフィールドのvalue属性には、入力ページから受け取った名前や性別などの値が指定されています。 そうすることで、「登録」ボタンがクリックされたときに、プロフィール登録ページのCGIプログラムへ、プロフィールの情報を送信することができるのです。

隠しフィールドを使用して、確認ページから登録ページへ情報を受け渡すようにしなさい。 上の例のように、確認ページにフォームを用意して、名前、性別、趣味、学年、コメントなどの情報を、隠しフィールドを使って送信するようにすること。 また、プロフィール確認ページから情報を受け取って表示する、プロフィール登録ページのCGIプログラムも作成しなさい。 (本当に登録する必要はありません。今回は受け取った情報を表示するだけでよい。)

作成したCGIプログラムと、完成したプロフィール入力ページのURLを提出してください。


課題1-2

人目に触れてはいけないパスワードなどの情報を送信するときは、<form>タグのmethod属性に"POST"を指定して情報を送信するようにします。 そうすることで、URLの後ろにパラメータが付加されなくなり、パスワードなどの秘密の情報が漏れるのを防ぐことができます。

11月(2)の課題2-3-1で作成したログインページとアカウント入力ページのフォームを修正して、送信後にブラウザのアドレスバーにパスワードが表示されないようにしなさい。

11月(2)の課題2-3-1で作成したログインページ
11月(2)の課題2-3-1で作成したアカウント入力ページ

[GETを指定してパスワードを送信すると危険な理由は?]

上のリンク先のログインページでは、<form>タグのmethod属性にGETを指定して情報を送信しています。 そのため、パスワード入力欄に入力された値はパラメータとして認証ページに送られてしまい、ブラウザのアドレスバーにパスワードの値が表示されてしまいます

さらに、アドレスバーに表示されるURLはそのまま履歴としてブラウザに記録されてしまいますので、正しいパスワードでログインしたときの履歴がブラウザに残っていると、履歴をクリックするだけで、他の人が簡単にログインできてしまいます

インターネットカフェなどの、不特定多数の人が共有して使用するコンピュータで、そのようなWebページにログインした場合にどうなるか、考えてみてください。

試しにアカウント名に「中京太郎」、パスワードに「aaa123」を入力してログインし、その後、別のウィンドウを開いて履歴を表示し、(他の人になったつもりで)履歴から「アカウント認証ページ」を開いてみましょう。 アカウント名やパスワードを入力していないのに、「ようこそ、中京太郎 さん。」と表示されてしまうはずです。

このような危険なシステムを作らないように、パスワードや個人情報などを含むデータを送信する場合には、<form>タグのmethod属性にPOSTを指定するようにしましょう。


課題1-3

今回学んだフォーム部品を使用して、11月(2)の課題1-2-4で作成した「背景と文字の色を変更することのできるCGIプログラム」を、もっと使いやすく便利なページになるように、自分で工夫して改良しなさい。

以下の解説が参考になるかもしれません。

[ラジオボタンの初期状態を指定するには]

ラジオボタンを最初から選択された状態にしておくときは、次のように<input>タグにcheckedと書いておきます。

  <input type="radio" name="パラメータ名1" value="値1" checked>文字1
  <input type="radio" name="パラメータ名1" value="値2">文字2
  <input type="radio" name="パラメータ名1" value="値3">文字3

同じパラメータ名のラジオボタンの中で、どれか一つだけにcheckedを付けることができます。 複数のラジオボタンを選択された状態にしておくことはできません。

[チェックボックスの初期状態を指定するには]

次のように、選択された状態にしておくチェックボックスにcheckedと書いておきます。

  <input type="checkbox" name="パラメータ名1" value="値1" checked>文字1
  <input type="checkbox" name="パラメータ名1" value="値2" checked>文字2
  <input type="checkbox" name="パラメータ名1" value="値3">文字3

ラジオボタンと違って、複数のチェックボックスを選択された状態にしておくことができます。

[セレクトボックスの初期状態を指定するには]

次のように、選択された状態にしておく選択肢の<option>タグにselectedと書いておきます。

  <select name="パラメータ名">
    <option value="値1">文字1</option>
    <option value="値2" selected>文字2</option>
    <option value="値3">文字3</option>
  </select>

一つのセレクトボックスの中で、どれか一つの選択肢にだけselectedを付けることができます。

作成したCGIのプログラムと、WebページのURLを提出してください。

プログラミングIIIのホームに戻る