# 14.3 フォームおよび検証のサポート
Web開発ではこのようなプロセスをよく見かけます：

- ページを開いてフォームを表示する。
- ユーザが入力を行い、フォームを送信する。
- もしユーザが無効な情報を送信した場合または何か必須項目を書き漏らしていた場合、フォームはユーザのデータとエラーの詳細情報を返す。
- ユーザが再度書き直し、上のプロセスを継続し、有効なフォームを送信する。

サーバのスクリプトでは必ず：

- ユーザが送信したフォームのデータを検証しなければなりません。
- データが正しい型、標準に適合しているか検証し、もしユーザ名が送信された場合、許された文字列のみを含んでいるか検証されなければなりません。これは最小の長さ以上最大の長さ以下でなければなりません。ユーザ名はすでに存在する他のユーザ名と重複してはいけません。とりわけ一つのキーワードについてもです。
- データをフィルタリングし危険な文字列を削除してロジックの処理において受け取るデータが安全であることを保証します。
- 必要であれば、データをあらかじめフォーマットします（データから空白文字やHTMLタグを削除するといったことです。）
- データが準備できると、データベースに保存します。

上のプロセスは特に複雑ということではありませんが、通常はとても多くのコードを書く必要があります。またエラー情報を表示するために、多くの場合ページに多くの異なるコントロール構造を使用します。フォームの検証を作成するのは簡単とはいいますが、実際に行うのはとても無味乾燥な作業です。

## フォームと検証
開発者にとって、開発のプロセスというものはとても複雑なものです。また、多くの場合同じ作業を何回も行うことになります。例えばシーンプロジェクトにおいてフォームデータを一つ追加する必要がでてきたとしましょう。この場合ローカルなコードの全体の流れをすべて修正する必要が出てきます。Goではstructはよく使われるデータ構造であることを知っています。そのため、beegoのformではstructを用いてフォームの情報を処理します。

まずWebアプリケーションを開発する時に対応するstructを定義します。ひとつのフィールドはひとつのform要素に対応しています。structのtagによって対応するよすおの情報と懸賞する情報を以下のように対応付けします：

	type User struct{
		Username 	string 	`form:text,valid:required`
		Nickname 	string 	`form:text,valid:required`
		Age			int 	`form:text,valid:required|numeric`
		Email 		string 	`form:text,valid:required|valid_email`
		Introduce 	string 	`form:textarea`
	}
	
structを定義したらcontrollerにおいてこのように操作します

	func (this *AddController) Get() {
		this.Data["form"] = beego.Form(&User{})
		this.Layout = "admin/layout.html"
		this.TplNames = "admin/add.tpl"
	}		
	
テンプレートで以下のようにフォームを表示します

	<h1>New Blog Post</h1>
	<form action="" method="post">
	{{.form.render()}}
	</form>
	
上では全体の第1ステップを定義しました。structからフォームを表示したあとは、ユーザが情報を入力し、サーバがデータを受け取って検証を行った後、データベースに保存されます。

	func (this *AddController) Post() {
		var user User
		form := this.GetInput(&user)
		if !form.Validates() {
			return 
		}
		models.UserInsert(&user)
		this.Ctx.Redirect(302, "/admin/index")
	}		
	
## フォームの型
以下のリストは対応するform要素の情報を表しています：
<table cellpadding="0" cellspacing="1" border="0" style="width:100%" class="tableborder">
<tbody><tr>
<th>名前</th>
<th>引数</th>
<th>機能の詳細</th>
</tr>

<tr>
<td class="td"><strong>text</strong></td>
<td class="td">No</td>
<td class="td">textbox入力欄</td>
</tr>

<tr>
<td class="td"><strong>button</strong></td>
<td class="td">No</td>
<td class="td">ボタン</td>
</tr>

<tr>
<td class="td"><strong>checkbox</strong></td>
<td class="td">No</td>
<td class="td">チェックボックス</td>
</tr>

<tr>
<td class="td"><strong>dropdown</strong></td>
<td class="td">No</td>
<td class="td">ドロップダウン</td>
</tr>

<tr>
<td class="td"><strong>file</strong></td>
<td class="td">No</td>
<td class="td">ファイルアップロード</td>
</tr>

<tr>
<td class="td"><strong>hidden</strong></td>
<td class="td">No</td>
<td class="td">hidden要素</td>
</tr>

<tr>
<td class="td"><strong>password</strong></td>
<td class="td">No</td>
<td class="td">パスワード入力欄</td>
</tr>

<tr>
<td class="td"><strong>radio</strong></td>
<td class="td">No</td>
<td class="td">ラジオボタン</td>
</tr>

<tr>
<td class="td"><strong>textarea</strong></td>
<td class="td">No</td>
<td class="td">テキストエリア</td>
</tr>

</tbody></table>

		
## フォームの検証
以下のリストは使用されるオリジナルのルールを表しています
<table cellpadding="0" cellspacing="1" border="0" style="width:100%" class="tableborder">
<tbody><tr>
<th>ルール</th>
<th>引数</th>
<th>詳細</th>
<th>例</th>
</tr>

<tr>
<td class="td"><strong>required</strong></td>
<td class="td">No</td>
<td class="td">要素が空だった場合、FALSEを返します</td>
<td class="td">&nbsp;</td>
</tr>

<tr>
<td class="td"><strong>matches</strong></td>
<td class="td">Yes</td>
<td class="td">もしフォームの要素の値と引数の対応するフォームのフィールドの値が等しくなければ、FALSEを返します</td>
<td class="td">matches[form_item]</td>
</tr>

  <tr>
    <td class="td"><strong>is_unique</strong></td>
    <td class="td">Yes</td>
    <td class="td">もしフォームの要素の値と指定されたデータ表に重複があった場合、Falseを返します（訳注：例えばis_unique[User.Email]とあれば、バリデーションクラスはUser表からEmail欄に要素と同じ値が無いか確かめます。もし重複が存在すれば、falseを返します。これにより開発者は他にCallbackバリデーションコードを書く必要がなくなります。）</td>
    <td class="td">is_unique[table.field]</td>
  </tr>

<tr>
<td class="td"><strong>min_length</strong></td>
<td class="td">Yes</td>
<td class="td">もしフォームの要素の値の文字列の長さが引数で定義された数字よりも少なかった場合、FALSEを返します。</td>
<td class="td">min_length[6]</td>
</tr>

<tr>
<td class="td"><strong>max_length</strong></td>
<td class="td">Yes</td>
<td class="td">もしフォームの要素の値の文字列の長さが引数で定義された数字よりも大きい場合、FALSEを返します。</td>
<td class="td">max_length[12]</td>
</tr>

<tr>
<td class="td"><strong>exact_length</strong></td>
<td class="td">Yes</td>
<td class="td">もしフォームの要素の値の文字列の長さが引数で定義された数字と異なっていた場合、FALSEを返します。</td>
<td class="td">exact_length[8]</td>
</tr>

  <tr>
    <td class="td"><strong>greater_than</strong></td>
    <td class="td">Yes</td>
    <td class="td">もしフォームの要素の値が数字型でないか、引数で定義された値よりも小さかった場合、FALSEを返します。</td>
    <td class="td">greater_than[8]</td>
  </tr>

  <tr>
    <td class="td"><strong>less_than</strong></td>
    <td class="td">Yes</td>
    <td class="td">もしフォームの要素の値が数字型でないか、引数で定義された値よりも大きかった場合、FALSEを返します。</td>
    <td class="td">less_than[8]</td>
  </tr>

<tr>
<td class="td"><strong>alpha</strong></td>
<td class="td">No</td>
<td class="td">もしフォームの要素の値にアルファベット以外の文字列が含まれていた場合、FALSEを返します。</td>
<td class="td">&nbsp;</td>
</tr>

<tr>
<td class="td"><strong>alpha_numeric</strong></td>
<td class="td">No</td>
<td class="td">もしフォームの要素の値にアルファベットか数字以外の文字列が含まれていた場合、FALSEを返します。</td>
<td class="td">&nbsp;</td>
</tr>

<tr>
<td class="td"><strong>alpha_dash</strong></td>
<td class="td">No</td>
<td class="td">もしフォームの要素の値にアルファベット/数字/アンダースコア/ダッシュ以外の文字列が含まれていた場合、FALSEを返します。</td>
<td class="td">&nbsp;</td>
</tr>

<tr>
<td class="td"><strong>numeric</strong></td>
<td class="td">No</td>
<td class="td">もしフォームの要素の値に数字以外の文字列が含まれていた場合、FALSEを返します。</td>
<td class="td">&nbsp;</td>
</tr>

<tr>
<td class="td"><strong>integer</strong></td>
<td class="td">No</td>
<td class="td">もしフォームの要素の中に整数以外の文字列が含まれていた場合、FALSEを返します。</td>
<td class="td">&nbsp;</td>
</tr>

  <tr>
    <td class="td"><strong>decimal</strong></td>
    <td class="td">Yes</td>
    <td class="td">もしフォームの要素に（少数でない）不完全な値が入力されていた場合、FALSEを返します。</td>
    <td class="td">&nbsp;</td>
  </tr>

<tr>
<td class="td"><strong>is_natural</strong></td>
<td class="td">No</td>
<td class="td">もしフォームの要素の値に自然数ではない他の数値が含まれていた場合（その他の数値には0は含みません）、FALSEを返します。自然数は：0,1,2,3....などです。</td>
<td class="td">&nbsp;</td>
</tr>

<tr>
<td class="td"><strong>is_natural_no_zero</strong></td>
<td class="td">No</td>
<td class="td">もしフォームの要素の値に自然数を除くその他の数値が含まれていた場合（その他の数値には0を含みます）、FALSEを返します。0でない自然数は：1,2,3.....などです。</td>
<td class="td">&nbsp;</td>
</tr>

<tr>
<td class="td"><strong>valid_email</strong></td>
<td class="td">No</td>
<td class="td">もしフォームの要素の値に正しくないemailアドレスが含まれている場合、FALSEを返します。</td>
<td class="td">&nbsp;</td>
</tr>

<tr>
<td class="td"><strong>valid_emails</strong></td>
<td class="td">No</td>
<td class="td">もしフォームの要素の値の中のある値に正しくないemailアドレス（アドレスの間はカンマで区切られています）を含んでいた場合、FALSEを返します。</td>
<td class="td">&nbsp;</td>
</tr>

<tr>
<td class="td"><strong>valid_ip</strong></td>
<td class="td">No</td>
<td class="td">もしフォームの要素の値が正しくないIPアドレスだった場合、FALSEを返します。</td>
<td class="td">&nbsp;</td>
</tr>

<tr>
<td class="td"><strong>valid_base64</strong></td>
<td class="td">No</td>
<td class="td">もしフォームの要素の値にbase64でエンコードされる文字以外の文字列が含まれる場合、FALSEを返します。</td>
<td class="td">&nbsp;</td>
</tr>

</tbody></table>


## links
   * [目次](<preface.md>)
   * 前へ: [Sessionのサポート](<14.2.md>)
   * 次へ: [ユーザの認証](<14.4.md>)
