laravelでformのバリデーションをしよう!(カスタマイズあり)


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

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

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

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

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

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

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

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

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

Laravelでformバリデーションをしよう!(標準装備編)

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

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


<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>

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

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

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

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


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文字以上」というバリデーションをつけています。

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


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

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

サポートURL: 全54種類!Laravel 5.7のバリデーション実例
サポートURL: Laravel公式サイト: バリデーション

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

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


<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を一気に表示したいなら、こんな感じになります


@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 で超ラクにバリデーションしてエラーメッセージを変更する

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

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

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

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

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


$ php artisan make:rule ValidateKana

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

そうすると、app/Rules/ValidateKana.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

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()]とコンマ区切りにしないとエラーが出ますので御気をつけください。

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

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


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

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

終わりに

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

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