| 説明 | フォームを示す |
|---|---|
| 語源 | FORM |
| 所属モジュール | Forms |
| 所属コンテントセット | Form |
| 内容 | Heading, Block-form, List |
| 内容の書式 | ( Heading | Block-form | List )+ |
| 関連項目 | なし |
| 公式な実装 | DTD |
| 属性 | 属性値の型 | 説明 |
|---|---|---|
| Common | [属性コレクション] |
XHTMLの要素が大抵持っている、一般的な属性を集めたコレクションです。 |
| 属性 | 属性値の型 | 説明 |
|---|---|---|
| action [必須] | URI (CDATA) |
フォームから送られたデータを処理するプログラムのURIを指定します。 |
| method | [選択] |
action属性で指定したプログラムにデータを送る時のHTTPメソッドを指定します。
|
| enctype | ContentType (CDATA) | |
| accept | ContentTypes (CDATA) |
action属性で指定したプログラムが処理可能なコンテントタイプを指定します。 |
| accept-charset | Charsets (CDATA) |
action属性で指定したプログラムが処理可能な文字エンコーディングを指定します。 |
| onsubmit | Script (CDATA) |
フォームのサブミットボタンが押された時に実行するスクリプトを記述します。 |
| onreset | Script (CDATA) |
フォームのリセットボタンが押された時に実行するスクリプトを記述します。 |
form要素は、フォーム (Form)を作ります。フォームというのは、大雑把に言って、閲覧者に何らかの情報を入力させ、サーバのプログラムに送信させる時のユーザーインターフェースです。例えば、掲示板の書き込みの際、名前や記事の内容を記入する部分もフォームとその部品で構成されていますし、オンラインショッピングサイトで、名前や住所、クレジットカード番号などを入力させるのもフォームを使って実現されています。
フォームを構成する各部品、例えば単一行のテキスト入力欄や、有効・無効を切り替えられるチェック欄、押す事でデータが送信されるボタンなどの部品は、コントロール (Control)と呼ばれます。各コントロールに入力された値、あるいは選択された値は、その入力値を識別する「名前」(name属性で記述)と共に、指定されたプログラムに送られます。つまり、ユーザはコントロールを通してプログラムと対話する訳です。
フォームで使用可能なコントロールは、次の通りです。
| タイプ | 説明 |
|---|---|
| プッシュボタン(Buttons) |
選択された時(フォーカスを得て押された時)、何らかの処理を行うものです。ボタンには3つの種類があります。
|
| チェックボックス(Checkboxes) |
チェックボックスは、オンとオフの二つの状態を持つ、ボタンの一種です。選択する事で状態をトグルさせる事ができます。 同じ名前を持つ複数のチェックボックスを作る事ができます。この場合、同じ名前を持つデータが複数送られてくる可能性があります。 |
| ラジオボタン(Radio Buttons) |
ラジオボタンも、オンとオフの二つの状態を持つボタンです。選択する事でオンにする事ができます。チェックボックスとの決定的な違いは、同じ名前を持つ複数のラジオボタンの内、オンにできるのはただ一つという事です。ある一つのラジオボタンをオンにすれば、同じ名前を持つ他のラジオボタンは全てオフになります。従って、同じ名前を持つデータが複数送られる事はありません。 |
| メニュー(Menus) |
メニューは、複数の選択肢の中から一つを選ばせるコントロールです。その役割ではラジオボタンに似ていますが、ユーザに表示される形態では異なっています。 メニューを作るにはselect要素を使います。size属性とmultiple属性を使えば、一つだけでなく複数の選択肢を選ばせる事も可能です。 |
| テキストボックス(Text Input) |
テキストボックスは、一行あるいは複数行のテキスト入力欄です。ユーザはキーボードなどを使って、任意の文字列をプログラムに渡す事ができます。 単一行テキストボックスを作るには、type属性がtextあるいはpasswordであるinput要素を、複数行テキストボックスを作るにはtextarea要素を使います。 |
| ファイル選択欄(File Select) |
ファイル選択欄は、指定されたファイルの内容をプログラムに送信する為のテキスト入力欄です。直接内容を記入するのではなく、ファイルの内容をユーザーエージェントが読み取ってアップロードしてくれる為、省力化もでき、バイナリデータもスマートに送れます。 |
| 隠しコントロール(Hidden Controls) |
隠しコントロールは、ユーザの目には見えないけれども、フォームの送信時には他のコントロールと一緒に送信されます。主に、入力を複数ページに分けて行わせるプログラムや、前回の入力結果を元に新しいページを作るプログラムが使用します。 |
| オブジェクトコントロール(Object Controls) |
汎用オブジェクトは、object要素から受け取るデータをそのまま送信するコントロールです。どのようなデータが送られるかは、データの種類によります。 |
Windowsでの呼称しか知らないのですが、対応表を載せておきます。
| Windowsでの呼称 | 対応するコントロール |
|---|---|
| ラベル(スタティックテキスト) | |
| テキストボックス(単一行) | |
| テキストボックス(単一行パスワード) | |
| テキストボックス(複数行) | |
| プッシュボタン | |
| チェックボックス | |
| ラジオボタン | |
| リストボックス | |
| コンボボックス(通常、ドロップダウン) |
|
| コンボボックス(ドロップダウンリスト) | |
| グループボックス | |
| その他 |
|
フォームの内容を送信するには、大きく分けて二つの方法があります。HTTPのGETメソッドを使う方法と、POSTメソッドを使う方法です。これらのメソッドは、フォームの送信の目的によって適宜使い分けます。詳しくはmethod属性を参照して下さい。
サクセスフルコントロール (Successful Control)という呼び方は奇妙に聞こえますが、要はフォームの送信ボタンが押された時に、名前と値のペアが送信されるコントロールの事です。例えば:
display : none;、あるいはvisibility : hidden;とされているようなコントロールもサクセスフルです。フォームの内容として送るべきデータを、action属性のプログラムに渡せるように整形するまでに、ユーザーエージェントは以下の手順を踏みます。
送信するフォームのform要素の子孫であるコントロールを調べ、その中でサクセスフルコントロールのみを拾い上げます。
全てのサクセスフルコントロールについて、コントロールの名前と値をペアにします。
enctype属性で指定されたエンコード方法を用いて、データセットを実際に送られる形にします。この値は大抵application/x-www-form-urlencodedですが、ファイルのアップロードをする場合などはmultipart/form-dataになります。
整形とは関係無いですが、ユーザーエージェントは送信が終わった後、サーバからの応答──即ち、プログラムの標準出力を読み取って表示します。
メソッドやエンコード方法などについて、現存する全てのものがサポートされている事は殆ど無いでしょうが、HTML4に対応していると謳っている(まともな)ユーザーエージェントは、次の二つの状況をサポートしています。
$ENV{"QUERY_STRING"}(文字列)でエンコード済みのデータセットを取得できますし、PHPならスーパーグローバル$_GET(連想配列)に、デコードされ、しかもペアごとに分けられた状態で取得できます。read( STDIN, $messageBody, $ENV{"CONTENT_LENGTH"} );で$messageBody(文字列)に読み取れますが、PHPの場合はこれもスーパーグローバル$_POST(連想配列)に、デコードされ、しかもペアごとに分けられた状態で取得できます。データセットをエンコードする時に使われる規則は、ContentTypeデータタイプとしてenctype属性で指定します。現存する全てのエンコード方法がサポートされているなんて事は無いでしょうが、次の二つは(まともなユーザーエージェントなら)必ずサポートされています。
URLエンコードは、コンテントタイプapplication/x-www-form-urlencodedで識別されるエンコード方法です。GETメソッドを使う場合は常にこの方法が使われ、POSTメソッドを使う場合でも大抵はこれが使われます(enctype属性の既定値です)。
URLエンコードを使う場合、ユーザーエージェントはまず、コントロールの名前とその値をエスケープ (使ってはまずい、あるいは使えない文字を使っても良い文字の組み合わせで表現する事)します。例えばスペースは'+'で、その他の使用不可の文字はパーセントエンコード (Percent Encode)されて'%'+'HH'(2桁の16進数)で表されます。例えば、改行はキャリッジリターン (Carriage Return、CR)とラインフィード (Line Feed、LF)の組(CR+LFと短縮される)で表されますが、これは%0D%0Aになります。また、テキストボックスに~x means a bitwise NOT, or a ones' complement.と入力された場合、これは%7Ex+means+a+bitwise+NOT%2C+or+a+ones%27+complement.とエンコードされます。
エンコードが終われば、ユーザーエージェントは、サクセスフルコントロールが文書中に現れた順番に、コントロールの名前と値をペアにします。名前と値は'='で分けられ、ペア同士は'&'で分けられます。例えば、次のようなフォームがあったとしましょう。
[プログラムコード開始]
[プログラムコード終了]
ここで、Word欄に~x、Description欄にMeans a bitwise NOT, or a ones' complement.と入力し、Submitボタンを押します。すると、ユーザーエージェントは、HTTPのGETメソッドを使って、www.example.comサーバに
[出力例開始]
[出力例終了]
URLエンコードは、データ量が少ない場合には適切で、しかもGETメソッドならURIとして入力した情報を保存できる為、例えばGoogleの検索結果に対してリンクを張るという事が可能でした。しかし、ASCII文字でないものが多く存在する時、例えば一般のファイル、日本語の長い文字列などではやたらとデータが長くなってしまいます。こういう場合、multipart/form-dataで識別されるマルチパート方式を採用するべきでしょう。
POSTメソッドでmultipart/form-dataエンコードを使うと、エンコードされたデータセットはメッセージボディとして送られる事はフォームの内容の整形で触れましたが、そのメッセージボディの中でも、各サクセスフルコントロールごとに区分されて送られます。
例えば、次のフォームを、値を変えずにそのまま送信してみたとしましょう。
[プログラムコード開始]
[プログラムコード終了]
これに対して、ユーザーエージェント、例えばMicrosoft Internet Exproler 6.0の場合、次のようなHTTPメッセージを送ります。
[出力例開始]
[出力例終了]
見て大体感じは掴めるかと思いますが、説明を加えていきましょう。
大量の'-'の後に16進数が並んでいる行は、パートバウンダリ (Part Boundaries)などと呼ばれるもので、サクセスフルコントロールを区切る為に使われます。このバウンダリは、Content-Typeヘッダで、Content-Type: multipart/form-data; boundary=---------------------------7d636d1010340のようにプログラムに渡されています。パートバウンダリは送信の度に変わりますし、ユーザーエージェントによって生成方法も違うので、必ず毎回Content-Typeヘッダを見る必要があります。ただ、送信されるデータの中にパートバウンダリが含まれる事は一切無い事が保証されています(ユーザーエージェントは、そうなるようにパートバウンダリを作り出します)。
よく数を数えてみると判りますが、Content-Typeヘッダで示されるバウンダリがそのまま使われている訳ではありません。サクセスフルコントロールの区切りには先頭に二つのハイフンが、データの終わりには先頭と末尾にそれぞれ二つのハイフンが付きます。これらによって、プログラムはサクセスフルコントロールごとにデータを分けて受け取る事ができます。
パートバウンダリによって分けられた各パートを見てみると、Content-Dispositionヘッダがあります。これは大抵Content-Disposition: form-data; name="コントロールの名前"の書式を持っています。ヘッダとデータ(コントロールの値)の間はCR+LF二つで分けられます(一行の空行ができる)。プログラムは次のバウンダリが現れるまでデータを読み取っていき、バウンダリが現れた所で最後のCR+LFを取り去ればコントロールの値が取得できる訳です。
コントロールの値に非ASCII文字が含まれる場合、何らかの手法でデータがエンコードされて送られる事があります。この時は、各パートのContent-Transfer-Encodingヘッダを見て、然るべき手法でデコードをしなければなりません。あるいは、エンコードされずに、Content-Typeヘッダが(HTTPメッセージのヘッダにではなく、各パートのヘッダに)付いている場合があります。この時は、charsetパラメータを見て内容を判断してやります。
フォームの中にファイル選択欄が含まれる場合、そのパートの中身はファイルの内容になります。例えば、次のフォームを考えます。
[プログラムコード開始]
[プログラムコード終了]
このフォームで、remote-fileのファイル選択欄でvalid-xhtml11.pngと入力し(実際には絶対パスで入力する事になるでしょう)、アップロードボタンを押すと、例えばIEでは次のようにメッセージが送られます。
[出力例開始]
[出力例終了]
local-nameの方は特筆すべき事はありませんが、remote-fileの方は少し違います。
まず、Content-Dispositionヘッダにfilenameパラメータが追加されます。これは必ず付いている保証はありませんが(強制はされていない)、余程の事情が無ければ付いているでしょう。filenameパラメータの値にはその名の通りファイル名(あるいはパス)が与えられますが、非ASCII文字が含まれている場合、エンコードされているかも知れません。
次に、Content-Typeヘッダが追加されます。これも強制されている訳ではありませんが、大抵付いている事でしょう。ただ、これが信用に値するかどうかは疑問です。中身がテキストファイルであっても知らない拡張子であればapplication/octet-streamになったり、上の例ではきちんと拡張子pngが付いているにも拘らず古いimage/x-pngで送られています。大概、本当に安全なファイルかどうかは、内容を見て決めなければならないでしょう。
また、ファイルの内容がエンコードされている場合には同様にContent-Transfer-Encodingヘッダが付きます。そして、エンコードの有無に拘らず、パートバウンダリはファイルの中身にも含まれない事が保証されています。
生のマルチパート形式を扱う上で必要な事は、大体こんな所でしょう。実際にこれを解釈しようとすると、それなりに面倒です。Perlでは生のままプログラム側で加工しなければならないので、ライブラリを自作するか、既にそういうものがあれば借りてくるのが楽でしょう。PHPなら、勝手にスーパーグローバル$_FILES(連想配列)に必要な情報をまとめてくれるので、扱いが非常に楽になります。$_POSTと併せれば言う事無しですね。本当にPHPは楽です。
これまでのコード例で気付いたかも知れませんが、form要素はInlineコンテントセットやPCDATAデータタイプを直下に持つ事はできないので、間に何かを噛ませる必要があります。解説ではあまり大きなフォームを作らなかったので全てdiv要素で済ませていますが、大きなフォームの場合はfieldset要素を使うと良いでしょう。
[プログラムコード開始]
[プログラムコード終了]
あんまり関係無いですが、個人情報を送る場合は、少なくともSSL が使われている事と、送信先が信頼の置けるものである事を確認しましょう。
| [form] | ||
|---|---|---|
| Published | : | 2006-03-26T09:00:00+09:00 |
| Last Modified | : | 2007-07-27T17:40:27+09:00 |
| Table of Contents | : | 要素目次 |
| Index | : | 要素索引 |
| Verified with | : |
|