# Form 的資料驗證

一般來說，我們會先在前端使用 JavaScript 做基本的資料檢查，但是我們也都知道，有心人士是可以跳過這個檢查，直接將資料送到後端的，所以後端的資料驗證是不可少的必要動作。

## Controller 的部份

Laravel 包含了一個 Validator 類別，專門用來處理資料驗證。

使用 Validator 類別的 make() 方法來建立驗證：

```
Validator::make(data, rules, messages, customAttributes)
```

* data：陣列。是準備要驗證的資料，也就是表單送過來的資料。
* rules：陣列。驗證規則。
* messages：陣列。驗證失敗後要回傳的訊息。
* customAttributes：自定屬性，可省略。

除了 data 及 rules，後面的兩個參數都可省略。

在迷你部落格的例子中，我們要驗證標題是否有填寫資料。首先，打開 app/controllers/HomeController.php，修改 store() 方法，加入驗證：

```
public function store()
{
    $input = Input::all();

    $rules = ['title' => 'required'];
    $messages = ['required' => '! 欄位不能空白'];

    $validator = Validator::make($input, $rules, $messages);

    if ($validator->passes()){
        $post = new Post;
        $post->title = $input['title'];
        $post->content = $input['content'];
        $post->save();

        return Redirect::to('post');
    }

    return Redirect::to('post/create')
            ->withInput()
            ->withErrors($validator);
}
```

說明：

Input::all() 會取得表單欄位及資料，以陣列的方式儲存，像這樣：

```
['title'=>'標題輸入的文字',
'content'=>'內容輸入的文字']
```

將它送給 Validator::make() 的第一個參數。

接著我們建立驗證規則：

```
$rules = ['title' => 'required'];
```

* title：是表單欄位的名稱。
* required：是關鍵字，表示這個欄位為必填，也就是不能空白。

註：可以在官網查詢更多的[驗證規則關鍵字](http://laravel.com/docs/4.2/validation#available-validation-rules)\[1]。

有了驗證規則，再來就是要指定，當驗證發生錯誤時，要回傳的錯誤訊息：

```
$messages = ['required' => '! 欄位不能空白'];
```

required 為關鍵字，對應到驗證規則裡所有指定為 required 的項目。值就是要顯示的訊息。

當 $validator->passes() 為 true 時，表示通過驗證，這時候才進行資料庫操作的動作。相反地，如果 $validator->fails() 為 true，表示驗證失敗，不做任何動作並返回表單頁面。

在驗證未過，返回表單頁面的同時，可以同時回傳使用者輸入的資料及錯誤訊息：

```
return Redirect::to('post/create')
            ->withInput()
            ->withErrors($validator);
```

重導頁面到 post/create 也就是表單頁面。withInput() 會同時把使用者有輸入資料的欄位的值回傳，所以回到表單頁面時，欄位中會有使用者剛剛填寫的資料，而不是空空的。withErrors() 則是把驗證結果回傳，這個動作會把錯誤訊息放入 session 中，View 在收到這個訊息時就可以顯示出來。

## View 的部份

編輯 app/views/site/create.blade.php，在原本的：

```
{{Form::text('title')}}<br>
```

下方，增加錯誤訊息的區塊：

```
{{ Form::text('title') }}
@if ($errors->has('title'))
    <div style="color:red;">{{ $errors->first('title') }}</div>
@endif
<br>
```

$errors 是 MessageBag 類別的實體。基本上，$errors 存在於每個 view 中，我們可以在有需要的時候才去呼叫它。而為什麼 $errors 會有我們回傳的 $validator 中的訊息呢？因為 Laravel 自動將它們綁定(bind)了。

檢查 $errors->has('title') 如果有資料才顯示我們的錯誤訊息 $errors->first('title')。

好了，你現在試著不要在標題中輸入任何資料，然後按"發表文章"按鈕，看看有沒有在欄位下方出現錯誤訊息。

另外可以試看看，當標題是空的，但是有輸入內容時，送出資料會發生什麼事？在標題顯示錯誤訊息的同時，內容的資料會被保留。假設你把 HomeController\@store 中的 ->withInput() 這一行拿掉，做同樣的動作，內容欄位就會被清空，而沒有被保留。

## 同一欄位，多個驗證規則

要對同一欄位加入多個驗證規則，每個規則必須用直線( | )分隔。

我們讓標題除了不能空白，還必須輸入超過 5 個字，在 HomeController\@store 中改兩行：

```
$rules = ['title' => 'required|min:5'];
$messages = ['required' => '! 欄位不能空白', 'min' => '! 必須超過5個字'];
```

min 是關鍵字，後面接數字。min:5 表示字數最少要 5 個字。同樣用 min 關鍵字設定錯誤訊息。

這樣就完成了，view 完全都不用改。現在標題輸入一個字，就會出現新的錯誤訊息了。

* \[1] <http://laravel.com/docs/4.2/validation#available-validation-rules>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tony915.gitbook.io/laravel-4-2/dong-shou-zuo-jin-jie/form-validation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
