Laravelのバリデーションオブジェクト
検証したバージョン
Laravel Framework 9.34.0
Laravel Framework 8.83.25
はじめに
Laravelにはデフォルトでバリデーションルールがあり、これを用いることで容易に簡潔なコードでバリデーションができます。
しかし、「記号を1文字以上含むパスワード」のような複雑なルールに対応しようとすると、長く読みづらいコードになってしまいます。
複雑な要件のバリデーションに対応したい場合は、パスワードルールオブジェクトが便利です。
パスワードルールオブジェクト
通常のバリデーションと同じように定義が可能です。
use Illuminate\Validation\Rules\Password;
public function rules()
{
return [
'password' => ['required', 'max: 128', Password::min(8)],
]);
定義できるルールには以下があり、これらを組み合わせることも可能です。
// 最低8文字必要
Password::min(8)
// 最低1文字の文字が必要
Password::min(8)->letters()
// 最低大文字小文字が1文字ずつ必要
Password::min(8)->mixedCase()
// 最低一文字の数字が必要
Password::min(8)->numbers()
// 最低一文字の記号が必要
Password::min(8)->symbols()
// パスワードリストに登録されているか確認
Password::min(8)->uncompromised()
最後のuncompromised()
は過去にデータ漏洩したことがあるかを確認してくれます。
例えば、脆弱なパスワードである "password" や "qwerty" などを入力すると引っかかります。ですので、パスワードの要件を縛りすぎることなく一部の危険なパスワードを回避することができます。さらに、半角全角英数字記号も満たしてるが脆弱な "Passw0rd!" などの設定も防ぐことが可能です。
また、引数に数値を入れることで、同一のデータリークにおいて、パスワードの出現回数がn回以下であることを確認することができます。
内部的には、have i been pwned のAPIを利用しているそうです。
日本語化
次に、日本語化の方法です。
検証したところ、8系と9系で設定方法が異なります。
※8系の方法は9系でも動作するためアップグレードする際には問題ありません。
Laravel9
validation.php
のpassword
を以下のように差し替えます。
'password' => [
'letters' => ':attributeは、少なくとも1つの文字が含まれていなければなりません。',
'mixed' => ':attributeは、少なくとも大文字と小文字を1つずつ含める必要があります。',
'numbers' => ':attributeは、少なくとも1つの数字が含まれていなければなりません。',
'symbols' => ':attributeは、少なくとも1つの記号が含まれていなければなりません。',
'uncompromised' => 'この:attributeは過去に漏洩したことのある脆弱な:attributeです。別の:attributeを入力してください。',
],
※翻訳内容は適時調整してください。
これで完了です。
Laravel8
実際に使うとこのような英語のメッセージが帰ってきます。 'パスワード' の文字だけ日本語になっている理由はこちらだけvalidation.php
によって設定されているからです。
バリデーション文の英語部分は
vendor/laravel/framework/src/lluminate/Validation/Rules/Password.php
に直に記述されており、validation.php
では設定できません。
なお、9系ではPassword.php
内で書き換えてから返す仕様に変わっており、設定が可能となっています。
9系、8系Password.php
差分(気になる方向け)
69c69
< * If the password should has not been compromised in data leaks.
---
> * If the password should not have been compromised in data leaks.
76c76
< * The number of times a password can appear in data leaks before being consider compromised.
---
> * The number of times a password can appear in data leaks before being considered compromised.
303,304d302
< $value = (string) $value;
<
306c304,307
< $validator->errors()->add($attribute, 'The :attribute must contain at least one uppercase and one lowercase letter.');
---
> $validator->errors()->add(
> $attribute,
> $this->getErrorMessage('validation.password.mixed')
> );
310c311,314
< $validator->errors()->add($attribute, 'The :attribute must contain at least one letter.');
---
> $validator->errors()->add(
> $attribute,
> $this->getErrorMessage('validation.password.letters')
> );
314c318,321
< $validator->errors()->add($attribute, 'The :attribute must contain at least one symbol.');
---
> $validator->errors()->add(
> $attribute,
> $this->getErrorMessage('validation.password.symbols')
> );
318c325,328
< $validator->errors()->add($attribute, 'The :attribute must contain at least one number.');
---
> $validator->errors()->add(
> $attribute,
> $this->getErrorMessage('validation.password.numbers')
> );
330,332c340
< return $this->fail(
< 'The given :attribute has appeared in a data leak. Please choose a different :attribute.'
< );
---
> return $this->fail($this->getErrorMessage('validation.password.uncompromised'));
345a354,376
> }
>
> /**
> * Get the translated password error message.
> *
> * @param string $key
> * @return string
> */
> protected function getErrorMessage($key)
> {
> if (($message = $this->validator->getTranslator()->get($key)) !== $key) {
> return $message;
> }
>
> $messages = [
> 'validation.password.mixed' => 'The :attribute must contain at least one uppercase and one lowercase letter.',
> 'validation.password.letters' => 'The :attribute must contain at least one letter.',
> 'validation.password.symbols' => 'The :attribute must contain at least one symbol.',
> 'validation.password.numbers' => 'The :attribute must contain at least one number.',
> 'validation.password.uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.',
> ];
>
> return $messages[$key];
そこで、以下をresources/lang/ja.json
に追加します。ja.jsonがない場合は作ってください。
{
"The :attribute must contain at least one uppercase and one lowercase letter.":":attributeは、少なくとも大文字と小文字を1つずつ含める必要があります。",
"The :attribute must contain at least one letter.":":attributeは、少なくとも1つの文字が含まれていなければなりません。",
"The :attribute must contain at least one symbol.":":attributeは、少なくとも1つの記号が含まれていなければなりません。",
"The :attribute must contain at least one number.":":attributeは、少なくとも1つの数字が含まれていなければなりません。",
"The given :attribute has appeared in a data leak. Please choose a different :attribute.":"この:attributeは過去に漏洩したことのある脆弱な:attributeです。別の:attributeを入力してください。"
}
はい、無事に日本語化が完了しました!!
便利な機能なので使っていない方はぜひ使ってみてください!