"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

はじめてLaravel6.0:バリデーション追加&カスタムバリデーション作成/windows10

Laravel6.0で、入力画面にバリデーションを組み込みます。

ついでに、Laravel組み込み以外に、カスタムバリデーションも作ります。

f:id:arakan_no_boku:20191003220222p:plain

 

 はじめに

 

今回は前回からの続きです。

arakan-pgm-ai.hatenablog.com

前回、入力画面をとりあえず作ってみました。

今回、それにバリデーションを追加してみようと思います。

もともと。 

Laravelには強力なバリデーションの仕組が用意されていて、標準で利用できるバリデーションルールも豊富です。

ドキュメントもしっかりしてて、使い方や、標準バリデーションルールの種類は、こちらのドキュメントを見れば、ほぼわかります。

readouble.com

とはいえ。

すべてが、標準のバリデーションルールでまかなえるわけもないので、カスタムバリデーションルールが必要になったりします。

ということで、今回はその両方をやってみようというわけです。

なお。

自分の環境だと、バリデーションのエラーメッセージは日本語になっています。

そのやり方は、こちらに書いてます。

arakan-pgm-ai.hatenablog.com

まだの方はどうぞ。

 

標準バリデーションルールを使ってみる

 

前回作成したのは、こんな画面です。

f:id:arakan_no_boku:20191023213830p:plain

bladeテンプレートで各項目には以下のnameを付けてます。

  • コード:code
  • 名前:name
  • カナ名:kana

前回は、一切バリデーションをかけずにいましたが、今回は、ここにバリデーションを追加していきます。

 

コントローラクラス(app\Http\Controllers\DummyController.php

 

Requestクラスのvalidateメソッドを使います。

修正後のソースコード全体はこちらです。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\DummyItem;

class DummyController extends Controller
{
   
    public function store(Request $request)
    {
        
        $request->validate([
            'code' => 'alpha_dash|max:10|min:4',
            'name' => 'min:2|max:20|regex:/^[^A-Za-z0-9]+$/u',
            'kana' => 'min:2|max:20|regex:/^[ァ-ヶ  ]+$/u',
        ]);
        
        $code = $request->code;
        $name = $request->name;
        $kana = $request->kana;
        $dummyItem = new DummyItem;
        $dummyItem->c_code = $code;
        $dummyItem->c_name = $name;
        $dummyItem->c_kana_name = $kana;
        $dummyItem->save();
        $msg = "登録プログラムで。「" .$code . " " . $name . " " . $kana . "」を登録しました。";
        return view('dummy', compact(
            'msg'
        ));
        
    }
}

今回追加したのは、この部分です。

$request->validate([
    'code' => 'alpha_dash|max:10|min:4',
    'name' => 'min:2|max:20|regex:/^[^A-Za-z0-9]+$/u',
    'kana' => 'min:2|max:20|regex:/^[ァ-ヶ  ]+$/u',
]);

標準のバリデーションルールを適用しています。

  • codeは「英数字のみで4文字以上10文字以下」
  • nameは「半角英数字以外で2文字以上20文字以下」
  • kanaは「全角カタカナと空白のみで2文字以上20文字以下」

 としています。

なお、「regex」バリデーションルールについて補足です。

これは内部でPHPの「preg_match」関数を使ってます。

なので、マルチバイト文字を条件に使うときは「/・・・/u」のように最後に「u」をつけてUTF-8を明示しないといけなかったりします。

 

View(resources\views\dummy.blade.php

 

コントローラクラスでバリデーションをかけてエラーになると、元画面にリダイレクトで戻ってきます。

リダイレクトだと普通にすると情報が引き継がれないので、Laravelが必要な情報をセッションに格納してくれてます。

View側では、それをセッションから取得して表示するための記述が必要になります。

今回必要な情報は以下です。

  • code,name,kanaに入力された値
  • 項目ごとのバリデーションエラーの有無
  • 項目ごとのバリデーションエラーメッセージ

基本的に、各項目に共通なので例として「code」の関連する部分だけを抜粋して、整理していきます。

<div class="form-group row">
   <label for="code" class="col-md-4 col-form-label text-md-right">コード</label>
      <div class="col-md-6">
          <input id="code" type="text" class="form-control @error('code') is-invalid @enderror" name="code" value="{{ old('code') }}" required autocomplete="code" autofocus>
          @error('code')
              <span class="invalid-feedback" role="alert">
                  <strong>{{ $message }}</strong>
              </span>
          @enderror
      </div>
</div>

ここで今回のポイントは以下です。

codeの入力値を復元するための「value="{{ old('code') }}"」。

エラーだった時にメッセージを表示するこの部分。

          @error('code')
              <span class="invalid-feedback" role="alert">
                  <strong>{{ $message }}</strong>
              </span>
          @enderror

ここの「$message」 は、コントローラクラスのどこにもでてきませんが、暗黙的にLaravelのバリデーション機構がエラーメッセージを格納してくれています。

そして。

<input>タグのclassに追加している以下の部分です。

@error('code') is-invalid @enderror

これは、エラーがあった時にテキスト入力フィールドの枠を赤くする指定です。

 

ここで一度実行してみます

 

上記のチェックを追加した状態で実行してみます。

こんな感じで入力してみました。

f:id:arakan_no_boku:20191023222602p:plain

登録ボタンを押すと。

f:id:arakan_no_boku:20191023222700p:plain

ちゃんといけてます。

 

カスタムバリデーションルールの作成と利用

 

カスタムバリデーションルールを作る手順は以下です。

  1. コマンドで枠になるクラスファイルを作る
  2. クラスにバリデーションロジックを組み込む
  3. コントローラクラスにバリデーションクラスを組み込む

さて。

やってみます。

 

コマンドで枠になるクラスファイルを作る

 

今回は試しに以下のルールを作ってみます。

氏名は「姓1文字以上」+「1つの空白」+「名1文字以上」の構造である。 

ルールクラスの名前は「KanjiName」にします。

コマンドはこうです。

php artisan make:rule KanjiName 

これで、「app\Rules」フォルダに「KanjiName.php」ができます。

生成される枠はこんな感じ。

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class KanjiName 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()
    {
        return 'The validation error message.';
    }
}

クラスにバリデーションロジックを組み込む

 

生成されたクラスの「passes」メソッドにチェックロジックを書きます。

そして「message()」メソッドのエラーメッセージを適切なものに書き換えます。 

修正したカスタムバリデーションクラスはこうです。

KanjiName.php

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class KanjiName 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)
    {
        mb_regex_encoding('UTF-8');
        $unicode_kanji_hira = '[ぁ-ん\x{2E80}-\x{2FDF}々〇〻\x{3400}-\x{4DBF}\x{4E00}-\x{9FFF}\x{F900}-\x{FAFF}\x{20000}-\x{2FFFF}]';
        $pattern = '^' . $unicode_kanji_hira . '+[  ]' . $unicode_kanji_hira . '+$';
        return mb_ereg($pattern, $value);
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return '氏名は「姓1文字以上+空白+名1文字以上」の形式である必要があります。';
    }
}

UNICODEの全角漢字・ひらがなにマッチする正規表現は、こちらを参考にしました。

UTF-8のコード表を見て自分でコードを拾うのは、とても面倒なので、助かります。

tama-san.com

こういう複雑な正規表現は「regex」ルールで書くと、ソースがごちゃごしゃしますから、カスタムルール化に適したお題になりました。

 

コントローラクラスにバリデーションクラスを組み込む

 

コントローラクラスに組み込みます。

これを利用する場合は、コントローラクラスの書き方がちょっと変わります。

カスタムルールのクラスオブジェクトを「new」してやる必要があるので、単純に文字列の中で「|」で連結する手段はとれません。

'name' => ['min:2', 'max:20', new KanjiName],

 みたいに、配列渡しをする必要があります。

その部分と、あとカナ名の部分も同様に「姓+空白+名」の形式のみOKにするルールに書き換えたコントローラクラスはこんな感じです。

DummyController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\DummyItem;

use App\Rules\KanjiName;

class DummyController extends Controller
{
   
    public function store(Request $request)
    {
        
        $request->validate([
            'code' => 'alpha_dash| max:10| min:4',
            'name' => ['min:2', 'max:20', new KanjiName],
            'kana' => 'min:2|max:20|regex:/^[ァ-ヶ]+[  ][ァ-ヶ]+$/u',
        ]);
        
        $code = $request->code;
        $name = $request->name;
        $kana = $request->kana;
        $dummyItem = new DummyItem;
        $dummyItem->c_code = $code;
        $dummyItem->c_name = $name;
        $dummyItem->c_kana_name = $kana;
        $dummyItem->save();
        $msg = "登録プログラムで。「" .$code . " " . $name . " " . $kana . "」を登録しました。";
        return view('dummy', compact(
            'msg'
        ));
        
    }
}
   

バリデーションルールの変更と、「use App\Rules\KanjiName;」を追加した以外の変更はありません。

 

さて実行してみます

 

まずは、エラーになるパターンから。

漢字氏名・カナ名とも、間に空白をいれない形にしています。

f:id:arakan_no_boku:20191024202511p:plain

きっちりエラーになります。

当然ですが、カスタムルールの方がメッセージも明確です。

f:id:arakan_no_boku:20191024202605p:plain

では姓と名の間に空白を入れる修正を施してみます。

f:id:arakan_no_boku:20191024202739p:plain

これで登録ボタンを押すと。

f:id:arakan_no_boku:20191024202822p:plain

きっちり登録されました。

カスタムバリデーションは、意図通り働いてくれています。

良い感じですね。

今回はこんなところで。

ではでは。