Laravel入門 Validationエラーのメッセージ表示と前回入力内容の表示&テスト(第13回)

2021-01-01
5 min read

Laravel での Validation エラーメッセージの表示方法とエラーメッセージの日本語対応を学びます。加えて、エラー前の入力内容を再表示する関数も学びます。

機能追加後のイメージ

下記の画面のような表示になるように機能を追加します。

task登録画面エラー

エラー表示

エラー表示には@errorディレクティブを使います。 使用方法は下記になります。

@error('title')
  <div class="alert alert-danger">{{ $message }}</div>
@enderror

@errorディレクティブの引数にてフィールドを指定します。上記ではtitleのエラーメッセージを指定しています。

バリデーションエラーについての公式ドキュメントの日本語訳は下記にあります。
https://readouble.com/laravel/7.x/ja/blade.html

viewにエラー表示を追加

resources/views/create-task.blade.phptitledescriptionにエラーメッセージが表示されるように@errorディレクティブを追加します。

<form method="POST" action="{{route('task.submit')}}">
    @csrf
    <div class="mb-3">
        <label class="form-label">title</label>
        <input name="title" class="form-control" type="text"
            placeholder="Text input" value="">
        @error('title')
        <div class="alert alert-danger">{{ $message }}</div>
        @enderror
    </div>

    <div class="mb-5">
        <label class="form-label">description</label>
        <textarea name="description" class="form-control" type="text"
            placeholder="Text input"></textarea>
        @error('description')
        <div class="alert alert-danger">{{ $message }}</div>
        @enderror
    </div>

    <div class="d-flex justify-content-end">
        <button class="btn btn-primary me-2">Submit</button>
        <a class="btn btn-secondary" href="{{route('home') }}">Cancel</a>
    </div>
</form>

ブラウザから、新規登録画面でエラーメッセージが表示されるように値を入力してSUBMITをクリックしてください。

エラーメッセージの日本語ファイルの用意

上記の修正でエラーメッセージが表示されるようにはなりましたが、エラーメッセージ文が英語です。 標準では、validation エラー時のメッセージが英語になります。 日本語のエラーメッセージが表示されるようにセットアップをします。 下記のコマンドを実行してください。

laravel6の場合

$ php -r "copy('https://readouble.com/laravel/6.x/ja/install-ja-lang-files.php', 'install-ja-lang.php');"
$ php -f install-ja-lang.php
$ php -r "unlink('install-ja-lang.php');"

laravel7の場合

$ php -r "copy('https://readouble.com/laravel/7.x/ja/install-ja-lang-files.php', 'install-ja-lang.php');"
$ php -f install-ja-lang.php
$ php -r "unlink('install-ja-lang.php');"

実行後は、resources/lang/ja/validation.phpが作成されています。

resources/lang/ja/validation.phpの最後の方に下記があります。

    /*
    |--------------------------------------------------------------------------
    | カスタムバリデーション属性名
    |--------------------------------------------------------------------------
    |
    | 以下の言語行は、例えば"email"の代わりに「メールアドレス」のように、
    | 読み手にフレンドリーな表現でプレースホルダーを置き換えるために指定する
    | 言語行です。これはメッセージをよりきれいに表示するために役に立ちます。
    |
    */

    'attributes' => [],

attributesに blade での項目名(name 属性)と日本訳を設定します。

    'attributes' => [
        'title'=>'タイトル',
        'description'=>'概要',
    ],

また、config/app.php'locale' => 'en'ja に変更します。

'locale' => 'ja',

config 系のファイルはキャッシュが優先されるので、キャッシュを削除し再作成を促します。

php artisan config:clear

ブラウザから、新規登録画面でエラーメッセージが表示されるように値を入力してSUBMITをクリックしてください。 エラーメッセージが日本語になっていることを確認してください

前回入力内容の表示

グローバルヘルパ関数 old 関数を利用します。 https://readouble.com/laravel/7.x/ja/helpers.html#method-old

Laravel では、前回の入力値がセッションに保存されます。

保存された値を取り出すための関数がold関数です。 Blade においては下記のように利用します。

value = "{{ old('title') }}"

エラー前の入力値を表示するようにviewを修正

<form method="POST" action="{{route('task.submit')}}">
    @csrf
    <div class="mb-3">
        <label class="form-label">title</label>
        <input name="title" class="form-control" type="text"
            placeholder="Text input" value="{{ old('title') }}">
        @error('title')
        <div class="alert alert-danger">{{ $message }}</div>
        @enderror

    </div>

    <div class="mb-5">
        <label class="form-label">description</label>
        <input name="description" class="form-control" type="text"
            placeholder="Text input" value="{{ old('description') }}">
        @error('description')
        <div class="alert alert-danger">{{ $message }}</div>
        @enderror
    </div>

    <div class="d-flex justify-content-end">

        <button class="btn btn-primary me-2">Submit</button>

        <a class="btn btn-secondary" href="{{route('home') }}">Cancel</a>
    </div>
</form>

ブラウザから、新規登録画面でエラーメッセージが表示されるように値を入力してSUBMITをクリックしてください。 SUBMITクリック前の入力内容が空にならずに表示されていることを確認してください。

テスト作成

項目別にエラーメッセージを確認します。

  • タイトルは必ず指定してください。
  • タイトルは、20 文字以下で指定してください。
  • 概要は、200 文字以下で指定してください。

項目別の前回入力内容の確認をします。

  • 前回のタイトルの入力文字列が表示される
  • 前回の内容の入力文字列が表示される

フューチャーテスト

フューチャーテストを作成します。

php artisan make:test TaskSubmitErrorMessageTest

テストケースを追加していきます。

タイトルは必ず指定してください。

public function testTitleNoTextError(): void
{
    $data = [
        'status' => 1,
        'title' => '',
        'description' => "description",
    ];
    $response = $this->from('/tasks/create')->post('/tasks', $data);

    $response->assertSessionHasErrors(['title' => 'タイトルは必ず指定してください。']);

    $response->assertRedirect('/tasks/create');
}

タイトルは、20文字以下で指定してください。

Str::random を使用するため、use \Str; を追加してください。

public function testTitleLongError(): void
{
    $data = [
        'status' => 1,
        'title' => Str::random(41),
        'description' => "description",
    ];
    $response = $this->from('/tasks/create')->post('/tasks', $data);

    $response->assertSessionHasErrors(['title' => 'タイトルは、40文字以下で指定してください。']);

    $response->assertRedirect('/tasks/create');
}

Str::random() という引数で指定した文字数分のテキストを生成してくれるクラスを使用しています。 use Illuminate\Support\Str;を追加してインポートしてください

概要は、200文字以下で指定してください。

public function testDescriptionLongError(): void
{
    $data = [
        'status' => 1,
        'title' => 'title',
        'description' => Str::random(201),
    ];
    $response = $this->from('/tasks/create')->post('/tasks', $data);

    $response->assertSessionHasErrors(['description' => '概要は、200文字以下で指定してください。']);

    $response->assertRedirect('/tasks/create');
}

フューチャーテストを実行します。

$ ./vendor/bin/phpunit tests/Feature/TaskSubmitErrorMessageTest.php

ブラウザテスト

エラーとなった時に、タイトル欄と概要欄に入力していた文字列が再表示されることを確認します。 SubmitTaskTestにそのためのテストメソッドを追加します。

    public function testOldValueDisp()
    {
        $this->browse(function (Browser $browser) {
            //タスク一覧画面からタスク新規登録画面へ
            $browser->visit('/')
            ->clickLink('+ Add')
            ->assertPathIs('/tasks/create')
            //フォームの入力
            ->type('title','タイトル1タイトル1タイトル1タイトル1タイトル1タイトル1タイトル1タイトル12' )
            ->type('description','本文1')
            ->press('Submit')
            //エラー後の再表示の確認
            ->assertPathIs('/tasks/create')
            ->assertInputValue('title','タイトル1タイトル1タイトル1タイトル1タイトル1タイトル1タイトル1タイトル12')
            ->assertInputValue('description','本文1');
        });
    }  

テストを実行します。

$ php artisan dusk tests/Browser/SubmitTaskTest.php
PHPUnit 9.5.1 by Sebastian Bergmann and contributors.

..                                                                  2 / 2 (100%)

Time: 00:01.356, Memory: 24.00 MB

OK (2 tests, 5 assertions)

完成です。