Laravelで独自バリデーションを実装する方法
Laravelには多彩なバリデーションが用意されています。大抵の場合はそれらを活用することでバリデーションを設定できますが、日本語独自のバリデーションなど、デフォルトの機能では実現できないものもあります。
そのような場合どうやって実装していくのかを紹介します。
目次
独自のバリデーションの作成
まずは独自バリデーションを定義します。
app/Validator.php
として配置します。
use Illuminate\Validation\Validator as BaseValidator;
/**
* カスタムバリデータ
*/
class Validator extends BaseValidator
Laravel上のVlidatorを継承して独自バリデーションClassを作成しています。
ただこのままでは独自バリデーションはフレームワーク上で認識されないので、サービスプロバイダを定義します。
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
use App\Validator as CustomValidator;
class ValidatorServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
Validator::resolver(function ($translator, $data, $rules, $messages, $attributes) {
return new CustomValidator($translator, $data, $rules, $messages, $attributes);
});
}
さらにconfig/app.phpのプロバイダに先ほどのバリデーションのサービスプロバイダを追記します。
'providers' => [
// 中略
App\Providers\ValidatorServiceProvider::class, // バリデーション用プロバイダ
],
独自バリデーションの例
ひらがな、カタカナのチェック
仮名入力などのチェックでひらがな、カタカナのチェックが必要ですが、Laravelの既存のバリデーションではチェックできません。そのため、次のような正規表現で実装します。
/**
* validateKatakana カタカナのバリデーション
*
* @param string $value
* @access public
* @return bool
*/
public function validateKatakana($attribute, $value, $parameters)
{
if(is_null($value)){
return true;
}
return (bool)preg_match('/^[ァ-ヾ 〜ー−]+$/u', $value);
}
/**
* validateHiragana ひらがなのバリデーション
*
* @param string $value
* @access public
* @return bool
*/
public function validateHiragana($attribute, $value, $parameters): bool
{
if(is_null($value)){
return true;
}
return (bool)preg_match('/^[ぁ-ん 〜ー−]+$/u', $value);
}
フォームリクエストでは次のようにバリデーションを設定できるようになります。
public function rules()
{
return [
'namekana' => [
'required',
'string',
'katakana', //全角カタカナチェック
'max:255',
],
必須チェックの強化
Laravelのバリデーションで必須の場合はrequiredとして定義します。ただ、これだけでは完全ではない場合があります。
formの値として空文字が送信された場合はエラーになりますが、そもそもform項目として存在しない場合バリデーションが実行されません。
氏名、フリガナといった項目はかならずform上で存在しますが、選択肢として複数項目を配列として指定するような画面の場合、追加ボタンを押下しないとform項目が出現しません。またアップロードする画像を指定しないとform項目が作成されないといったパターンがあります。
そういった何も送信されない場合でも必須チェックをかける場合は以下のようなバリデーションを作成します。
public function validateImplicitRequired($attribute, $value, $parameters): bool
{
return !is_null($value);
}
public function validateImplicitRequiredIf($attribute, $value, $parameters): bool
{
$param0 = explode('.', $parameters[0]);
if(count($param0) == 2){
if(request()->input($param0[0])[$param0[1]] == $parameters[1]){
return !is_null($value);
}
}elseif(request()->input($parameters[0]) == $parameters[1]){
return !is_null($value);
};
return true;
}
内部的にはLarvel自体のrequired、required_ifと同じ処理です。このままでは結局フォーム値として送信しないとバリデーションが実行されません。そのために暗黙の拡張に追加する必要があります。
class Validator extends BaseValidator
{
public function __construct($translator, $data, $rules, $messages = [], $attributes = [])
{
parent::__construct($translator, $data, $rules, $messages, $attributes);
// required系の独自バリデーションは暗黙の拡張に追加
$implicit_rules = [
'ImplicitRequired',
'ImplicitRequiredIf',
];
$this->implicitRules = $implicit_rules;
}
こうすることでimplicit(暗黙)の必須チェックを実装できます。
あとはフォームリクエストのrequiredを下記のように置き換えるだけです。
public function rules()
{
return [
'choices' => [ //選択肢の配列のバリデーション
'implicit_required',
'array',
],
バリデーションエラーメッセージの調整
エラーメッセージを定義しないとLaravelデフォルトの英文エラーメッセージになってしまうので、言語設定ファイルで独自バリデーションのエラーメッセージを追加する必要があります。
<?php
return [
/*
|--------------------------------------------------------------------------
| バリデーション言語行
|--------------------------------------------------------------------------
|
| 以下の言語行はバリデタークラスにより使用されるデフォルトのエラー
| メッセージです。サイズルールのようにいくつかのバリデーションを
| 持っているものもあります。メッセージはご自由に調整してください。
|
*/
// 中略
/* 追加エラーメッセージ */
'implicit_required' => ':attributeは必須項目です。',
'implicit_required_if' => ':attributeは必須項目です。',
'katakana' => ':attributeは全角カタカナで入力してください。',
'hiragana' => ':attributeは全角ひらがなで入力してください。',
まとめ
単純な文字種チェックだけではなく、より複雑なものも独自バリデーションで実装可能になります。
例えばヘアサロンの予約で、「あなたはすでに同じ時間帯で予約済みです。」といった入力チェックも可能になります。
amazonでも同様のバリデーションがあれば嬉しいのですが、残念ながら実装されていません。同じコミックを間違って2冊買って、ダブったものをBookoffに売りに行くことが何度かありました…
こういったことが起きないようにユーザに優しい細やかなバリデーションを実装していきましょう。



















