Study & Practice

北海道札幌市のプログラマによる技術とか雑記のブログ

LaravelのValidationを使ってみる

5月から参画したチームがLaravelを使っていまして、ちょいちょい不具合修正のチケットなんかを担当し始めた。しかし、Laravelの機能がまだあんまりわかってないもので既存のコードを読むのに時間がかかってしまっています。ということで公式ドキュメントを読んでいろんな機能を使ってみようと思います。今回はその第一弾、Validation機能を使っていきます。

laravel.com

下準備

まずは下準備です。

以下のコマンドでコントローラーを追加します。

php artisan make:controller ValidationController

コントローラーにview表示用のメソッドを追加します。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ValidationController extends Controller
{
    // 追加
    public function index()
    {
        return view('validation');
    }

    // 追加
    public function validation(Request $request)
    {
        echo "name: $request->name<br>";
        echo "email: $request->email<br>";
    }
}

以下のコマンドでviewを追加

touch resources/views/validation.blade.php

resources/views/validation.blade.phpの内容は以下のようにします。

<form method="POST" action="/validation">
    @csrf
    <label>Name</label>
    <input id="name" name="name" type="text">
    <br>
    <label>Email</label>
    <input id="email-address" name="email" type="email">
    <button type="submit">Submit</button>
</form>

最後にweb.phpにValidationController::index()とValidationController::validation()へのルーティング設定を追加します。

<?php

use App\Http\Controllers\ValidationController;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

// 追加
Route::get('/validation', [ValidationController::class, 'index']);
Route::post('/validation', [ValidationController::class, 'validation']);

これでhttp://localhost:8000/validationにブラウザからアクセスすると

f:id:carametal:20210623203734p:plain
こんな感じのシンプルなフォームが出来上がります。

そしてNameとEmailに適当な文字列を入れてSubmitを押すと以下のような出力がされるはずです。

name: test name
email: test@example.com

これで下準備が完了です。

基本的なValidationの使い方

それではValidationの機能を使っていきます。

まずはValidationControllerのvalidationメソッドを以下のように更新します。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ValidationController extends Controller
{
    public function index()
    {
        return view('validation');
    }

    // 更新
    public function validation(Request $request)
    {
        $request->validate([
            'name' => 'required|max:10',
            'email' => 'required|max:20'
        ]);
        echo "name: $request->name<br>";
        echo "email: $request->email<br>";
    }
}

Requestのvalidateメソッドが公式ドキュメントで一番最初に紹介されるValidation機能です。今回のコードはリクエストのnameとemail両方を必須項目として、nameを最大10文字、emailを最大20文字の制限をつけています。

ただ、実行していただければわかるかと思いますが、validationでエラーになるデータをPOSTしてもFormの画面に戻されるだけでエラーなどが表示されませんので、エラーメッセージの表示機能を追加してみます。

<form method="POST" action="/validation">
    @csrf
    <label>Name</label>
    <input id="name" name="name" type="text">
    <br>
    <label>Email</label>
    <input id="email-address" name="email" type="email">
    <button type="submit">Submit</button>
</form>

{{-- 追加 --}}
@if ($errors->any())
    <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
    </ul>
@endif

validationがエラーになると自動的に元の画面にリダイレクトされます。$errorsという変数にエラーメッセージが格納されているため、上記のように取り出して画面上に表示することができます。

ためしにNameとEmailをどちらも入力せずにSubmitを押してみると以下のようなエラーメッセージが表示されます。

The name field is required.
The email field is required.

どちらの項目も必須項目に設定してあるためfield is requiredのメッセージが出ます。

次はNameを11文字以上、Emailを21文字以上にしてみましょう。

The name must not be greater than 10 characters.
The email must not be greater than 20 characters

今度はmust not be greater thanのメッセージが出ました。意図した通りにValidationが効いていますね。


ちなみに今回のような規定のvalidationを使用している場合、resources/lang/en/validation.phpでエラーメッセージを編集することができます。定義されている連想配列の中からrequired、maxとそれぞれのキーを探して値として設定されているエラーメッセージを編集してください。

※上記のファイルは英語用のファイルとして定義されています。日本語用のファイルを設定したい方は以下を参考にしてください。
laravel.com

Form Requestを使ったValidation

次はForm Request機能を使ったValidationを試してみます。

Form Requestはartisanコマンドで作ることができます。

php artisan make:request ValidationRequest

app/Http/Requests/ValidationRequest.phpを以下のように書き換えます。

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ValidationRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        // false -> true
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        // 更新
        return [
            'name' => 'required|max:15',
            'email' => 'required|max:25'
        ];
    }
}

Validationの内容が一緒だと変化したかわかりずらいのでそれぞれmaxを15と25に設定してみました。これでコントローラーのValidationが不要になったので削除します。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ValidationController extends Controller
{
    public function index()
    {
        return view('validation');
    }

    // 更新
    public function validation(ValidationRequest $request)
    {
        $request->validated();
        echo "name: $request->name<br>";
        echo "email: $request->email<br>";
    }
}

$request->validated();のでForm Requestで設定したValidationを呼び出しています。早速使ってみましょう。

The name must not be greater than 15 characters.
The email must not be greater than 25 characters.

それぞれ15文字と25文字の制限になりましたね。これでForm RequestのValidationを実装できました。

ちなみにForm Requestではエラーメッセージのカスタムもできます。やってみましょう

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ValidationRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required|max:15',
            'email' => 'required|max:25'
        ];
    }

    // 追加
    public function messages()
    {
        return [
            'name.required' => 'Name is required.',
            'name.max' => 'Name must be less than 15 characters.',
            'email.required' => 'Email is required.',
            'email.max' => 'Email must be less than 25 characters.',
        }
    }
}

messages()メソッドはFormRequestクラスに定義されており、それをオーバーライドする形で定義します。requestのキーとValidationのルール名をドットで繋ぐ記法を使っています。上記のコードでそれぞれを未入力のままSubmitすると

Name is required.
Email is required.

ちゃんと反映されてますね。

Nameを16文字以上、Emailを26文字以上入力すると

Name must be less than 15 characters.
Email must be less than 25 characters.

こちらもちゃんと反映されてますね。

それとattributes()メソッドをオーバーライドすることで汎用的なエラーメッセージを作ることもできます。

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ValidationRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required|max:15',
            'email' => 'required|max:25'
        ];
    }

    // 追加
    public function attributes()
    {
        return [
            'name' => 'Name',
            'email' => 'Email'
        ];
    }

    public function messages()
    {
        return [

            '*.required' => ':attribute is required.',
            'name.max' => 'Name must be less than 15 characters.',
            'email.max' => 'Email must be less than 25 characters.',
        ];
    }
}

このようにすることで:attributeの部分がnameのエラーではName、EmailのエラーではEmailという表示をしてくれるようになります。

Validationのリダイレクト先の指定

Validationでエラーになった場合に元の画面ではなく、特定の指定した画面にリダイレクトさせたい場合があると思います。その場合はValidator::make()メソッドを使うことができます。

<?php

namespace App\Http\Controllers;

use App\Http\Requests\ValidationRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class ValidationController extends Controller
{
    public function index()
    {
        return view('validation');
    }

    public function validation(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|max:15',
            'email' => 'required|max:25'
        ]);

        if($validator->fails()) {
            return redirect('/error');
        }
        echo "name: $request->name<br>";
        echo "email: $request->email<br>";
    }
}

fails()メソッドはValiationでエラーが発生した際に、trueを返します。なのでエラーが発生したら/errorにリダイレクトするという処理になります。

リダイレクト先が必要になるので以下のようにルーティングを追加してください。

<?php

use App\Http\Controllers\ValidationController;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

Route::get('/validation', [ValidationController::class, 'index']);
Route::post('/validation', [ValidationController::class, 'validation']);

// 追加
Route::get('/error', function() {
    return 'ERROR.';
});

これでValidationでエラーが出るデータを入力してsubmitすると

ERROR.

と表示されるはずです。

まとめ

ということでValidation機能を使ってみました。今回はrequiredとmaxしかしようしていませんが、組み込みのValidationルールは数多くあるので是非公式ドキュメントを見て使ってみてください。

laravel.com