laravelでformのバリデーションをしよう！（カスタマイズあり）


Laravelにはformバリデーションができる便利な機能があります！！

今回はそれを紹介していきます！

標準でもかなりの種類のバリデーションをサポートをしていますが、バリデーションを自分仕様にカスタマイズしたい時もあるので、カスタマイズバージョンも説明します！


# formバリデーションはどんなことができるか

例えば、こんなログイン画面があるとします

![スクリーンショット 2019-03-03 13.17.20.png](https://qiita-image-store.s3.amazonaws.com/0/238739/65740b4c-f221-6804-6fe1-d8117a957a85.png)


ユーザーがメールアドレスを入力せずにログインボタンを押した場合は、

![スクリーンショット 2019-03-03 13.18.47.png](https://qiita-image-store.s3.amazonaws.com/0/238739/65086a78-28cb-6fe4-f56a-73edc3a10b93.png)

「emailは必須項目です。」というエラーが出ます。

仕様としてはこんな感じです！

じゃあ次はどうやってバリデーションをするかみてみましょう〜


# Laravelでformバリデーションをしよう！（標準装備編）

## バリデーションをする前のbladeをみる

先ほどのログイン画面のformの部分のbladeはこんな感じにしています。
（バリデーションを実装する前です。）

```html

<form class="register-form" action="/login" method="post">
    {{ csrf_field() }}
    <div class="email-login-form-title">メールアドレス</div>
    <div class="email-login-form-input"><input type="email" name="email"　value="{{old('email')}}"></div>

    <div class="email-login-form-title">パスワード</div>
    <div class="email-login-form-input"><input type="password" name="password"></div>
    <button type="submit">ログイン</button>
</form>
```

まあまあ普通のシンプルなログインフォームですよね。

これでログインボタンを押した場合は、コントローラに`email`、`password`の値が送信されます。
(inputのnameの部分が名前で、テキストボックスに入力された値がコントローラにいきます。)


## コントローラでバリデーションをしてみる

LoginControllerの中にあるログインをするための関数です。


```php

class LoginController extends Controller
{
.
.
    protected $redirectToAfterLogin = '/home';

    /**
     * login
     */
    public function login(Request $request)
    {
        $validator = $request->validate([       // <-- ここがバリデーション部分
            'email' => 'required|exists:users',
            'password' => 'required|min:8',
        ]);
        $user = User::where('email', $request->email)->first();
        Auth::login($user);
        return redirect($this->redirectToAfterLogin);
    }
.
.
.
}

```


もうなんかみたらなんとなくわかると思うんですけど、`email`には、「必須項目」「ユーザーが既にデータベースに存在する」というバリデーション、`password`には「必須項目」「8文字以上」というバリデーションをつけています。


バリデーション部分の書き方については、

```php

$request->validate([
    '$requestの中に入っている要素' => '実行したいバリデーションを「|」区切りで書く',
]);
```


そして、大事なところは、**`$request->validate...`のところでバリデーションに引っかかったらそこで処理を中止して、ビューにエラーを返す**ということです。

サポートURL: [全54種類！Laravel 5.7のバリデーション実例](https://blog.capilano-fw.com/?p=341)
サポートURL: [Laravel公式サイト: バリデーション](https://readouble.com/laravel/5.5/ja/validation.html)


## ビューでエラーを表示する

ビューでエラーを表示するには、ビューをこのように変更します。

```html

<form class="login-form" action="/login" method="post">
    {{ csrf_field() }}
    <div class="email-login-form-title">メールアドレス</div>
    <div class="email-login-form-input"><input type="email" name="email" value="{{old('email')}}"></div>
    @if ($errors->first('email'))   <!-- ここ追加 -->
        <p class="validation">※{{$errors->first('email')}}</p>
    @endif

    <div class="email-login-form-title">パスワード</div>
    <div class="email-login-form-input"><input type="password" name="password"></div>
    @if ($errors->first('password'))　　　<!-- ここ追加 -->
        <p class="validation">※{{$errors->first('password')}}</p>
    @endif
    <button type="submit">ログイン</button>
</form> 
```

emailのバリデーションのエラーなら、`$errors->first('email')`で取得できます。

全てのerrorを一気に表示したいなら、こんな感じになります

```html

@if ($errors->any())
    @foreach ($errors as $error)
        <p class="validation">{{$error}}</p>
    @endforeach
@endif
```

## CSSでvalidationのスタイルを追加したら終わり！

validationでエラーが出た時の、エラーメッセージのスタイルはぜひ統一しておきたいので、
validationのcssを書いたら終了です。

先ほどのログイン画面はちなみにこういうcssを書いていましたが、みなさんお好きにどうぞ。。。
```css
.validation {
    display: inline;
    font-size: 0.8rem;
    color: #FA5C65;
    margin: 0.3rem;
}
```


## ちょっと待って！エラー文が英語じゃねえか！！

そうなんです。最初はエラー文は英語で用意されているんです。

僕はこれをまんまパクりました↓

[Laravel5.3 で超ラクにバリデーションしてエラーメッセージを変更する
](https://qiita.com/komatzz/items/422bcba9847ca3a79fe9)

ただ、今はlaravel5.7だか5.8だかその辺りなので、気をつけてください。


# Laravelでformバリデーションをする（カスタマイズ編）

カスタマイズって難しそうに聞こえますけど、結構簡単です！

じゃあ例えば、カタカナしか入力して欲しくないフォームを作るとしましょう。

まずは、コマンドを叩きます。

```bash

$ php artisan make:rule ValidateKana
```

ValidateKanaの部分は、名前はなんでも大丈夫です。

そうすると、`app/Rules/ValidateKana.php`ができています。

これをみると最初はこうなっていると思います

```php

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class ValidateKana implements Rule
{
    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        // 
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        // 
    }
}
```

`passes`関数のところに、どういうバリデーションをしたいかを記述し、
`message`関数のところに、エラーメッセージに内容を記述します。


カタカナ以外の文字が送られてきた場合、「カタカナで入力してください」と返すとすると、ValidateKanaはこうなります。
（passesでfalseがreturnされた時にエラーが発動します。$valueは入力された値をさしています。）

```php

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class ValidateKana implements Rule
{
    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        if (preg_match("/^[ｦ-ﾟｰ ]+$/u", $value) || preg_match('/^[ァ-ヾ]+$/u', $value)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'カタカナで入力してください';
    }
}
```


ほんで、Controllerの方では、このように書きます。
`new ValidateKana()`で先ほどのカスタマイズしたカタカナバリデーションが発動しています。

```
class LoginController extends Controller
{
    use App\Rules\ValidateKana;
.
.
.
    public function 〇〇
    {
        $validator = $request->validate([
            'koumokumei' => ['required', 'string', new ValidateKana()],
        ])
    }

```

## 注意点

ちなみに、お気付きの方もいらっしゃるかもしれませんが、
カスタマイズしたバリデーションを追加すると、「|」バリデーションの書き方は区切りじゃなくなるんです。

今までは`['required|string']`のように書いていましたが、カスタマイズが登場するだけで
`['required', 'string', new ValidateKana()]`とコンマ区切りにしないとエラーが出ますので御気をつけください。




# 補足：バリデーションの機能を使わずにバリデーションっぽいことしたい！！


そんなニーズがあるかはわかりませんが、
こうやったらできます。

```php

return redirect('/')->withErrors("エラーが発生しました");
```

これでビューの方に$errorsを渡します。


# 終わりに

Laravelで簡単formバリデーション講座を行いました。

標準だけでもものすごいパターンのバリデーションができるので、めちゃくちゃおすすめです！