Laravelのバリデーションについて複数あるじゃないか！

Laravelにはデフォルトで洗練された
「フォームリクエストバリデーション」というものがある。

これは

```
・フォームを含む各リクエストに対して、それぞれ固有のバリデーションを設定できる。
・バリデーションエラー時には、入力値とエラー情報を付与して前のページに自動的にリダイレクトする。
・バリデーションをパスした時に初めてコントローラー内の処理に移る。
```

というものである。

非常に優秀かつ優れたものだと思う。


## 目的

バリデーションは複数あるので
自分の求める目的に合わせて利用してほしい

そして誰かの参考になればよいと思い記事をかく

## 環境


| 名前 | バージョン |
|:----:|:----:|
| Laravel | 5.0 |
| php | 5.6 |
| macOS Sierra | 10.12.6 |

## 入力値の受け取り方

検索時

- name:book_id
- name:book_name

の２つのフォームがあるとする


## [Validation1] Laravel Validationを利用する

上記でも述べましたが
Laravelのデフォルトで搭載されている
バリデーション機能は

```
・フォームを含む各リクエストに対して、それぞれ固有のバリデーションを設定できる。
・バリデーションエラー時には、入力値とエラー情報を付与して前のページに自動的にリダイレクトする。
・バリデーションをパスした時に初めてコントローラー内の処理に移る。
```

となっております。

### 直コントローラ書き

まずコントローラの
(Request $request)があるメソッドに

```php
$this->validate($request, [
       'book_id'    => '条件',
       'book_name'  => '条件',
]);
```

このような記載をする

条件に関してはこちらを参考にしてください

[Laravelのバリデーションで指定できる内容をざっくりまとめ直しました。](http://qiita.com/fagai/items/9904409d3703ef6f79a2)

今回は

| name | 条件 |
|----|----|
| book_id | 整数<br>1文字以上12文字以下 |
| book_name | 文字列<br>1文字以上12文字以下 |

という条件にしようと思うので


```php:controller
$this->validate($request, [
       'book_id'    => 'integer|between:1,12',
       'book_name'  => 'string|between:1,12',
]);
```

とこのように書くことができます。

この状態でフォームを送信してもなにもメッセージは得られません

のでviewの方で以下のような記載をしてください

#### 【特定の場所で全表示】

```php:view
@if(count($errors) > 0)
    <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
    </ul>
@endif
```

#### 【特定の場所で特定のエラーを出す】

```php:view
@if($errors->has('book_id'))
    <div class="error">
        <p>{{ $errors->first('book_id') }}</p>
    </div>
@endif
```

この状態で違反する内容でフォームを送信しましょう

エラーメッセージとして
よくわからないエラーが出ると思います。

これをカスタマイズするには以下のようにします

```php:controller
$this->validate($request, [
       'book_id'    => 'integer|between:1,12',
       'book_name'  => 'string|between:1,12',
],[
       'book_id.integer'    => '整数でお願い',
       'book_name.between'  => 'ここは:minから:maxまでの長さなのじゃよ',
]);
```

### リクエストクラスの作成

Artisanコマンドで一発で作成可能です

```
$ php artisan make:request RegisterFormRequest
```

利用するためには
コントローラでこのリクエストクラスを利用する設定をします

```php:controller
use App\Http\Requests\RegisterFormRequest;

...

public function registerForm(RegisterFormRequest $request)
```

あとはメソッド単位でホゲホゲしてあげる。

以上！！！


## [Validation2] 自分で作っちゃおうぜ

自分で作るメリットとしては
細かく自由にカスタマイズし放題
デメリットとしては時間がかかる…？
だと思います

### コントローラで作成

まず条件としては上と同じく

| name | 条件 |
|----|----|
| book_id | 整数<br>1文字以上12文字以下 |
| book_name | 文字列<br>1文字以上12文字以下 |

こちらでやります。

まずはrequestされてきた値を配列に格納し
トリムなんかを施して
バリデーション用のメソッドへ飛ばします

```php:controller
public function registerForm(Request $request) {
// 検索フォームに入力された値を取得する
    $input = $request->all();
// 前後の全角スペースを削除する
	$inputs = [];
	foreach($input as $key => $val) {
		$inputs[$key] = trim($val, " \t\n\r\0\x0B　");
		$inputs[$key] = ltrim($val, "0");
	}
// エラーチェック
    $formErrors = $this->isValidate($inputs);
```


その値を受け取ります
何かのエラー処理を行った後その値をreturnさせます

```php:controller
public function isValidate(array $inputs) {

    $errors = [];
    $errors = [
    'book_id'   => "",
    'book_name' => "",
    ];

return $errors
```

その値を表示させるためには
viewの方で以下のようにしてあげましょう

※すごい雑なやり方です。
本来であればboolでやるのが理想かと

```php:view
@if($formErrors['book_id']!="")
    <div class="error">
        <p>{{ $formErrors['book_id'] }}</p
    </div>
@endif
```

これで下準備はできました

あとはバリデーションチェックです

### バリデーション

必須項目のチェック

```php:isValidateのメソッド
// BookIDのチェック
if (!empty($inputs['book_id'])) {
	$str = "";
	$str = $inputs['book_id'];
	if ($this->isNumeric($str) === false){
		$errors['book_id'] = 'BookIDは整数のみじゃよ！';
	}
}
```

```php:isNumericのメソッド
function isNumeric($str) {
    if (!preg_match("/^[0-9]+$/", $str)) {
        # 半角数字以外が含まれていた場合、false
        return false;
    }
    return true;
}
```

こんな感じですかね…。
これで1つのフォームで複数のエラーを持たせてあげてforeachで回すのがいいかもしれません。



## まとめ

今回

エラーでもその入力値で問い合わせはする、フォームも入力値のまま
エラーメッセージは表示させたい
ということだったので下のような感じになりました。

もし上記の条件でもっといいやり方があれば
教えてください。