BeginnerEngineerBlog
中の人
中の人

【laravel validator】validatorクラスでよく使うやつのメモ

公開: 2023-08-19 12:44
更新: 2023-08-26 21:00
879
laravel6.x validator
validatorクラスよく使うのでメモ

こんにちは!

中の人です

個人的にフォームリクエストよりvalidatorクラスを使うほうが好きです

ということでvalidatorクラスでよく使う内容をメモとして紹介します!

※ 紹介するコードは勝手にlaravelチュートリアルで作成したTutorialアプリを利用しています


基本的なバリデート


ベーシックなやつ

📁 root/app/Http/Controllers/ArticleController.php

<?php

use Illuminate\Support\Facades\Validator;
// ...省略

    public function create(Request $request)
    {
        // 👇こっから
        $validator = Validator::make($request->all(), [
            'title' => [
                'required',
                'string',
                'max:25',
            ],
            'content' => [
                'required',
                'string',
                'max:4000',
            ],
            'tag' => [
                'nullable',
                'string',
            ],
        ]);
        $validator->validate();
        // 👆ここまでのやつ
        $id = $request->get('id');
        $article = Article::find($id);
        
        //...省略


        return redirect()->route('article.show', ['id' => $article->id]);
    }

個人的には別ファイルに$validatorを返す関数を作って利用してますが、まぁお好きにという感じで

これでvalidateに引っかかった場合、リクエストを送った画面に入力した値やエラーメッセージを持ってリダイレクトしてくれます

表示するテンプレートは

📁 root/resources/views/article/new.blade.php

@extends('layouts.app')
@section('content')
    <form action="{{route('article.create')}}" method="post">
        @csrf
        <input type="hidden" name="id" value="{{$id ?? null}}">
        <div class="form-row">
            <div class="form-group col-sm-6">
                <label>Title</label>
                <input
                    name="title"
                    type="text"
                    value="{{old('title', $title ?? null)}}"
                    class="form-control
                    @error ('title') is-invalid @enderror"
                >
                @error('title')
                    <ul class="invalid-feedback">
                        @foreach ($errors->get('title') as $message)
                            <li>
                                {{$message}}
                            </li>
                        @endforeach
                    </ul>
                @enderror
            </div>
            <div class="form-group col-sm-6">
                <label>Tag</label>
                <input
                    type="text"
                    name="tag"
                    value="{{old('tag', $tag ?? null)}}"
                    class="form-control @error ('tag') is-invalid @enderror"
                    placeholder="separated by ,"
                >
                @error('tag')
                    <ul class="invalid-feedback">
                        @foreach ($errors->get('tag') as $message)
                            <li>
                                {{$message}}
                            </li>
                        @endforeach
                    </ul>
                @enderror
            </div>
        </div>
        <div class="form-row">
            <div class="form-group col-sm-6">
                <label>Content</label>
                <textarea
                    name="content"
                    cols="30"
                    rows="10"
                    class="form-control @error ('content') is-invalid @enderror"
                >{{old('content', $content ?? null)}}</textarea>
                @error('content')
                    <ul class="invalid-feedback">
                        @foreach ($errors->get('content') as $message)
                            <li>
                                {{$message}}
                            </li>
                        @endforeach
                    </ul>
                @enderror
            </div>
            <div class="form-group col-sm-6 d-flex align-items-end">
                <input type="submit" class="btn btn-primary">
            </div>
        </div>
    </form>
@endsection

(Tutorialアプリから少し修正してます)

以下が動作



いい感じにバリデートされてます

カスタムバリデート


独自にバリデーションを実装したい場合

after


afterはValidator::make関数の第二引数のルールを検証した後に実行される関数です。

        $validator = Validator::make($request->all(), [
            'title' => [
                'required',
                'string',
                'max:25',
            ],
            'content' => [
                'required',
                'string',
                'max:4000',
            ],
            'tag' => [
                'nullable',
                'string',
            ],
            // 👇 これ
        ])->after(function (\Illuminate\Contracts\Validation\Validator $validator) {
            if (empty($validator->failed())) { // 👈 ルールの検証で問題なければ
                $params = $validator->getData(); // 👈 値を取得
                if ($params['title'] !== 'おすおす') {
                    // 👇 titleを指定してエラーメッセージを設定
                    $validator->errors()->add('title', 'おすおすちゃうやん');
                }
            }
        });
        $validator->validate();



カスタムエラーメッセージ


そのまま表示


titleの必須バリデーションのエラーメッセージを変更します

        $validator = Validator::make($request->all(), [
            'title' => [
                'required',// 👈 これ
                'string',
                'max:25',
            ],
            'content' => [
                'required',
                'string',
                'max:4000',
            ],
            'tag' => [
                'nullable',
                'string',
            ],
        ],[
            'title.required' => '(゚∀゚ )おすおす',// 👈 これ
        ])->after(function (\Illuminate\Contracts\Validation\Validator $validator) {
            if (empty($validator->failed())) {
                $params = $validator->getData();
                if ($params['title'] !== 'おすおす') {
                    $validator->errors()->add('title', 'おすおすちゃうやん');
                }
            }
        });


Validator::make関数の第三引数に配列で指定することができます


フォーム名を入れて表示


        $validator = Validator::make($request->all(), [
            'title' => [
                'required',
                'string',
                'max:25',
            ],
            'content' => [
                'required',
                'string',
                'max:4000',
            ],
            'tag' => [
                'nullable',
                'string',
            ],
        ],[
                                 // 👇 これ
            'title.required' => ':attributeは(゚∀゚ )おすおす',
        ])->after(function (\Illuminate\Contracts\Validation\Validator $validator) {
            if (empty($validator->failed())) {
                $params = $validator->getData();
                if ($params['title'] !== 'おすおす') {
                    $validator->errors()->add('title', 'おすおすちゃうやん');
                }
            }
        });

:attribute


                <input
                    name="title" // 👈 こいつ
                    type="text"
                    value="{{old('title', $title ?? null)}}"
                    class="form-control
                    @error ('title') is-invalid @enderror"
                >

name属性の値が入ります


ちなみに

        ])->after(function (\Illuminate\Contracts\Validation\Validator $validator) {
            if (empty($validator->failed())) {
                $params = $validator->getData();
                if ($params['title'] !== 'おすおす') {
                                                        // 👇 これ
                    $validator->errors()->add('title', ':attributeはおすおすちゃうやん');
                }
            }
        });


これは無理っぽい

フォーム名をカスタムして表示


        $validator = Validator::make($request->all(), [
            'title' => [
                'required',
                'string',
                'max:25',
            ],
            'content' => [
                'required',
                'string',
                'max:4000',
            ],
            'tag' => [
                'nullable',
                'string',
            ],
        ],[
            'title.required' => ':attributeは(゚∀゚ )おすおす',
        ])->after(function (\Illuminate\Contracts\Validation\Validator $validator) {
            if (empty($validator->failed())) {
                $params = $validator->getData();
                if ($params['title'] !== 'おすおす') {
                    $validator->errors()->add('title', 'おすおすちゃうやん');
                }
            }
            // 👇 これ
        })->setAttributeNames([
            'title' => 'タイトル',
        ]);

setAttributeNames()

この関数の引数に配列を渡して、任意のフォーム名を指定することができます



終わりに


冒頭でフォームリクエストよりvalidatorクラスが好きと書きましたが、理由は例えば、ファイルアップロード処理などした際、ファイルのバリデーションは突破してるけど、別のバリデーションが引っかかってリダイレクトした際に、アップロードしたファイルが消えてしまいますよね。
なので、よくやる実装として、ファイルを仮アップロードしてリダイレクトのような処理を実装すると思いますが、フォームリクエストの中でアップロード処理実装する?という問題というかジレンマというかに毎回悩まされます。

validatorクラスの場合、ほとんどコントローラ内で実装することが多いと思いますし、

$validator->validate();
// 👇リダイレクトする前に追加の処理をしたい場合下記のように書き換え
if ($validator->fails()) {
    // 追加の処理追加
    return redirect()
        ->back()// 👈 直前の画面へ
        ->withInput()// 👈 投げた値の保持
        ->withErrors($validator);// 👈 エラーメッセージの保持
}

これで、バリデートに引っかかった場合の処理がコントローラ内で書けるので、私個人としては腑に落ちるんですよね

ただ、調べたところフォームリクエストでリダイレクトさせない方法もあるみたいです。

まぁ、フォームリクエストもvalidatorクラスもその時々で使い分けるのが正解ということですね!
結論どっちでもいいよねってことかな!

ということで

おすー(゚∀゚ )
0
0
0
0
通信エラーが発生しました。
【広告】
似たような記事