質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.53%

フォームリクエストを利用してのバリデーション実装と日本語化について

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 1,260

djkddsjk

score 10

前提・実現したいこと

現在、Laravel5.4にて、フォームリクエストを利用して、バリデーションの実装をしようとしております。
どのようにしましたら、以前のように、1つの項目名に対して複数のエラーを表示させることができるのでしょうか?

また、中途半端な日本語になってしまっているバリデーションエラーメッセージを、設定した日本語での表示に切り替えることができるのでしょうか?

フォームリクエストを利用する以前に、コントローラにバリデーションを書いていたときには、設定した項目名に対して、複数のエラーが生じた際には、複数のメッセージが表示されていたのですが、フォームリクエストを利用してからは、1つの項目名に対して、1つのエラーのみ表示されるようになってしまいました。

テンプレートには、$errors->first(項目名)ではなく、$errors->get(項目名)を使用し、
もしも、@errors に値が保管されている場合は、$errors からエラーメッセージをまとめて取り出して、@foreach を使い、順に出力していくようにしているつもりです。

どのようにしましたら、以前のように、1つの項目名に対して複数のエラーを表示させることができるのでしょうか?

また、エラーメッセージにつきましても、日本語にしようとしているのですが、それも中途半端になってしまっております。
日本語の設定をしているつもりのバリデーションルールも、日本語が当てがわれて表示されていない状態です。
私のブラウザ環境では、required は設定した日本語に変わっておりますが、文字数のバリデーションルールにつきましては、元の英語のままとなってしまっております。

そちらにつきましても、どのようにしましたら良いのでしょうか? 

ご教示いただけますでしょうか? 何卒よろしくお願い申し上げます。

発生している問題・エラーメッセージ

以下は、ブラウザでのバリデーションエラーメッセージです。

ERORR        The age must be between 0 and 150. ← こちらが日本語になりません。
ERORR        お名前は必ずご入力してください。 ← こちらは設定した日本語の通りに表示されております。

該当のソースコード

Laravel5.4

HelloRequest.php

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

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

        if($this->path() === 'hello'){
            return true;
        } else {
            return false;
        }

    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required|string|between:2, 40',
            'mail' => 'required|email',
            'age' => 'numeric|between:0, 150',
        ];
    }


    public function messages()
    {
        return [
            'name.required' => 'お名前は必ずご入力してください。',
            'name.string' => 'お名前は文字でのご入力をお願いいたします。',
            'name.between:2,40' => 'お名前は2文字以上、40文字以内にてお願いいたします。',
            'mail.required' => 'メールアドレスは必ずご入力してください。。',
            'mail.email' => 'メールアドレスの形式になっておりません。',
            'age.numeric' => 'ご年齢は整数でのご入力をお願いいたします。',
            'age.between:0,150' => 'ご年齢は 0 〜 150 の間でご入力をお願いいたします。',
        ];
    }

}

index.blade.php

@section('content')
    <p>{{$msg}}</p>
    @if (count($errors) > 0)
        <p>入力に問題があります。再入力してください。</p>
    @endif
    <table>
        <form class="" action="/hello" method="POST">
            {{ csrf_field() }}
            @if ($errors->has('name'))
                <tr><th>ERORR</th><td>@foreach ($errors->get('name') as $error)
                    <td>{{ $error }}</td>
                @endforeach</td></tr>
            @endif
                <tr><th>name:</th><td><input type="text" name="name" value="{{ old('name') }}"></td></tr>
            @if($errors->has('mail'))
                <tr><th>ERORR</th><td>@foreach ($errors->get('mail') as $error)
                    <td>{{ $error }}</td>
                @endforeach</td></tr>
            @endif
                <tr><th>mail:</th><td><input type="text" name="mail" value="{{ old('mail') }}"></td></tr>
            @if($errors->has('age'))
                <tr><th>ERORR</th><td>@foreach ($errors->get('age') as $error)
                    <td>{{ $error }}</td>
                @endforeach</td></tr>
            @endif
                <tr><th>age:</th><td><input type="text" name="age" value="{{ old('age') }}"></td></tr>
            <tr><th></th><td><button type="submit" name="" value="send">送 信</button></td></tr>
        </form>
    </table>
@endsection

補足情報(言語/FW/ツール等のバージョンなど)

Laravel5.4

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

 エラーメッセージが日本語にならない

https://readouble.com/laravel/5.4/ja/validation.html

「カスタムエラーメッセージ」項を参照してください。

そちらを見ていただくとわかると思うのですが、betweenの場合のエラーメッセージの書き方が誤っています。

    public function messages()
    {
        return [
            'name.required' => 'お名前は必ずご入力してください。',
            'name.string' => 'お名前は文字でのご入力をお願いいたします。',
//            'name.between:2,40' => 'お名前は2文字以上、40文字以内にてお願いいたします。',
            'name.between' => 'お名前は :min 文字以上、:max 文字以内にてお願いいたします。',
            'mail.required' => 'メールアドレスは必ずご入力してください。。',
            'mail.email' => 'メールアドレスの形式になっておりません。',
            'age.numeric' => 'ご年齢は整数でのご入力をお願いいたします。',
//            'age.between:0,150' => 'ご年齢は 0 〜 150 の間でご入力をお願いいたします。',
            'age.between' => 'ご年齢は :min 〜 :max の間でご入力をお願いいたします。',
        ];
    }

と変更すれば日本語になるのではないかと思いますが、お試しいただけますか?(動作未検証)

 エラーメッセージが1つしか表示されない

ご質問の件に入る前に……。  
(直接の原因かどうかはわかりませんが)テーブルタグの構造がおかしいようです。

↓例:年齢のエラーメッセージ

            @if($errors->has('age'))
                <tr><th>ERORR</th><td>@foreach ($errors->get('age') as $error)
                    <td>{{ $error }}</td>
                @endforeach</td></tr>
            @endif

こちら、エラーメッセージが2つだったとして
<tr><th>ERORR</th><td><td>{{ $error }}</td><td>{{ $error }}</td></td></tr>

という構造になってしまっています(<td>タグの中にまた<td>が入っている)。

エラーメッセージが増える度にテーブルタグの<td>を増やしていくのは現実的ではないと思いますので、

            @if($errors->has('age'))
                <tr><th>ERORR</th><td>@foreach ($errors->get('age') as $error)
                    {{ $error }}<br/>
                @endforeach</td></tr>
            @endif

            @if($errors->has('age'))
                <tr><th>ERORR</th><td>@foreach ($errors->get('age') as $error)
                    <p>{{ $error }}</p>
                @endforeach</td></tr>
            @endif

等に変更してください。


まずは、上記を修正していただき「エラーメッセージがきちんと表示できる状態」にしてください。

その上で、肝心な「エラーメッセージが1つしか表示されない」についてですが……。

betweenの挙動が入力値の型によって変わってしまうため(数値の場合は値チェック、文字列の場合は文字数チェック)、「エラーが1つしか出ていない」のか「本当はエラーが2つあるのに、出力だけが1つになっている」のか判別がつきにくいですね。

どちらの問題なのか切り分けるために、テスト的に、name欄に文字種制限(英字のみ可:alpha)をかけてみていただけますか?

    public function rules()
    {
        return [
//            'name' => 'required|string|between:2, 40',
            'name' => 'required|string|alpha|between:2, 40',
            'mail' => 'required|email',
            'age' => 'numeric|between:0, 150',
        ];
    }

この状態で、41文字以上、かつ、アルファベットだけではない文字列(例: aaaaabbbbbcccccddddd11111222223333344444a )を入力し、結果を確認してみてください。

  • エラーメッセージが2つ表示された(文字数エラー&文字種エラー):
    「複数エラーメッセージを取得する」処理は正しく行えているようです。
    既存のバリデーションでエラーメッセージが1つしか出力されないのは、「メッセージが出力されない」ではなく、betweenの仕様(データ型によってチェック内容が変わってしまう)のせいで、エラーチェックが1つずつしか行われていないのではないかと思われます。

  • エラーメッセージが1つしか表示されない:
    エラーメッセージの出力方法に問題があるのかもしれません(処理を拝見する限り、マニュアルどおりのように見受けられるのですが……)。
    試しに $errors->all() で全てのエラーメッセージを確認すると、どうなっていますか?
    https://readouble.com/laravel/5.4/ja/validation.html

追伸:
「エラー」のtypoが散見されますので、ついでに修正されることをおすすめします(ERORR → ERROR)。
 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/11 17:55

    nak様、本当にありがとうございます。解決できました!

    ご教示いただきました、alpha での検証及び、html の修正、between の書き方(完全に間違って覚えておりました..大変申し訳ございません.)等、すべて私の方でも検証させていただきました。
    エラーメッセージが1つしか表示されないの件につきましても、ご指摘いただきました検証方法にて複数表示を確認できました。ありがとうございます。$errors->all()や、私が元々書いていた$errors->get('name')でも、複数表示を確認できました。追伸いただきました ERROR 部分も修正し、わかりやすくなったかと思います。

    本当に助かりました、ありがとうございます!

    キャンセル

  • 2017/10/12 13:09

    諸々ご確認&ご報告ありがとうございました。
    解決されたのでしたら何よりです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.53%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる