Livewireのバリデーションは、Laravelの標準的なフォームバリデーションと同じように感じるはずです。つまり、Livewireは、コンポーネントごとにバリデーションルールを設定するための$rules
プロパティと、それらのルールを使用してコンポーネントのプロパティをバリデートするための$this->validate()
メソッドを提供しています。
Livewireにおけるフォームのバリデーションの簡単な例をご覧ください。
class ContactForm extends Component
{
public $name;
public $email;
protected $rules = [
'name' => 'required|min:6',
'email' => 'required|email',
];
public function submit()
{
$this->validate();
// バリデーション失敗の場合、ここまで実行されない
Contact::create([
'name' => $this->name,
'email' => $this->email,
]);
}
}
<form wire:submit.prevent="submit">
<input type="text" wire:model="name">
@error('name') <span class="error">{{ $message }}</span> @enderror
<input type="text" wire:model="email">
@error('email') <span class="error">{{ $message }}</span> @enderror
<button type="submit">Save Contact</button>
</form>
バリデーション失敗の場合、標準のValidationException
が投げられ(そして、Livewireがキャッチして)、標準の$errors
オブジェクトがコンポーネントのビュー内で利用可能になります。このため、アプリケーションの残りの部分でバリデーションを処理するBladeインクルードのような既存のコードも同様に適用されます。
カスタムキー/メッセージのペアをエラーバッグに追加することもできます。
$this->addError('key', 'message')
動的にルールを定義する必要がある場合は、コンポーネントの$rules
プロパティをrules()
メソッドで代用できます。
class ContactForm extends Component
{
public $name;
public $email;
protected function rules()
{
return [
'name' => 'required|min:6',
'email' => ['required', 'email', 'not_in:' . auth()->user()->email],
];
}
}
リアルタイムバリデーション
ユーザーがフォームフィールドに入力するときに、フォームフィールドをバリデートすると便利な場合があります。Livewireでは$this-> validateOnly())
メソッドを使用して、「リアルタイム」検証が簡単に行えます。
更新のたびに入力フィールドをバリデートするには、Livewireのupdated
フックを使用します。
class ContactForm extends Component
{
public $name;
public $email;
protected $rules = [
'name' => 'required|min:6',
'email' => 'required|email',
];
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function saveContact()
{
$validatedData = $this->validate();
Contact::create($validatedData);
}
}
<form wire:submit.prevent="saveContact">
<input type="text" wire:model="name">
@error('name') <span class="error">{{ $message }}</span> @enderror
<input type="text" wire:model="email">
@error('email') <span class="error">{{ $message }}</span> @enderror
<button type="submit">Save Contact</button>
</form>
この例で実際何が起こっているのか分析してみましょう。
- ユーザーは"name"フィールドに入力します
- ユーザーが名前を入力すると、6文字未満の場合にはバリデーションメッセージが表示されます
- ユーザーはメールの入力に切り替えることができますが、名前に対するバリデーションメッセージは引き続き表示されます
- ユーザーがフォームを送信すると、最終的なバリデーションチェックが行われ、データが保持されます。
もしかしたらあなたは、「なぜvalidateOnly
が必要なのですか?validate
だけを使用することはできませんか?」と疑問に思っているでしょう。この理由は使用しない場合、あるフィールドを更新するたびにすべてのフィールドがバリデートされるためです。これは不快なユーザーエクスペリエンスになる可能性があります。フォームの最初のフィールドに1文字を入力すると、突然すべてのフィールドにバリデーションメッセージが表示されることを想像してみてください。validateOnly
はこれを防ぎ、更新している現在のフィールドのみバリデートします。
$rules
プロパティ外のルールで検証する
何らかの理由で$rules
プロパティで定義するルール以外のルールを使用して、バリデーションしたい場合は、ルールをvalidate()
やvalidateOnly()
メソッドに直接渡し、いつでも検証できます。
class ContactForm extends Component
{
public $name;
public $email;
public function updated($propertyName)
{
$this->validateOnly($propertyName, [
'name' => 'min:6',
'email' => 'email',
]);
}
public function saveContact()
{
$validatedData = $this->validate([
'name' => 'required|min:6',
'email' => 'required|email',
]);
Contact::create($validatedData);
}
}
エラーメッセージと属性をカスタマイズする
Livewireコンポーネントで使用するバリデーションメッセージをカスタマイズしたい場合は、$messages
プロパティを使用してカスタマイズできます。
デフォルトのLaravelバリデーションメッセージを保持したまま、メッセージの:attribute
部分だけをカスタマイズしたい場合は、$validationAttributes
プロパティを使用して、カスタム属性名を指定できます。
class ContactForm extends Component
{
public $email;
protected $rules = [
'email' => 'required|email',
];
protected $messages = [
'email.required' => 'The Email Address cannot be empty.',
'email.email' => 'The Email Address format is not valid.',
];
protected $validationAttributes = [
'email' => 'email address'
];
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function saveContact()
{
$validatedData = $this->validate();
Contact::create($validatedData);
}
}
グローバルな$rules
バリデーションプロパティを使用しない場合は、カスタムメッセージと属性をvalidate()
へ直接渡せます。
class ContactForm extends Component
{
public $email;
public function saveContact()
{
$validatedData = $this->validate(
['email' => 'required|email'],
[
'email.required' => 'The :attribute cannot be empty.',
'email.email' => 'The :attribute format is not valid.',
],
['email' => 'Email Address']
);
Contact::create($validatedData);
}
}
エラーメッセージの直接操作
validate()
とvalidateOnly()
メソッドで、ほとんどのケースを処理できるはずですが、Livewireの内部ErrorBagを直接制御したい場合もあるでしょう。
Livewireには、ErrorBagを直接操作するためにメソッドをいくつか用意しています。
Livewireコンポーネントクラス内のどこからでも、以下のメソッドを呼び出すことができます。
// 手早くエラーバッグに検証メッセージを追加します。
$this->addError('email', 'The email field is invalid.');
// この2つの方法はエラーバッグをクリアするという同じ動作をします。
$this->resetErrorBag();
$this->resetValidation();
// 1つのキーのエラーのみをクリアする場合は、以下を使用します。
$this->resetValidation('email');
$this->resetErrorBag('email');
// 次の方法で、エラーバッグに完全にアクセスできます。
$errors = $this->getErrorBag();
// このエラーバッグインスタンスを使用し、以下のようなことが可能です。
$errors->add('some-key', 'Some message');
バリデーションのテスト
Livewireは、バリデーションシナリオに役立つテストユーティリティを提供しています。「お問い合わせフォーム」コンポーネントの簡単なテストを書いてみましょう。
/** @test */
public function name_and_email_fields_are_required_for_saving_a_contact()
{
Livewire::test('contact-form')
->set('name', '')
->set('email', '')
->assertHasErrors(['name', 'email']);
}
これも便利ですがさらに一歩進んで、特定のバリデーションルールに対して実際にテストすることができます。
/** @test */
public function name_and_email_fields_are_required_for_saving_a_contact()
{
Livewire::test('contact-form')
->set('name', '')
->set('email', '')
->assertHasErrors([
'name' => 'required',
'email' => 'required',
]);
}
LivewireはassertHasErrors
の逆な、assertHasNoErrors()
も提供します。
/** @test */
public function name_field_is_required_for_saving_a_contact()
{
Livewire::test('contact-form')
->set('name', '')
->set('email', 'foo')
->assertHasErrors(['name' => 'required'])
->assertHasNoErrors(['email' => 'required']);
}
これら2つのメソッドでサポートしているその他の構文例については、テストのドキュメントを参照してください。
カスタムバリデタ
Livewireで独自のバリデーションシステムを使用したい場合も問題ありません。LivewireはValidationException
をキャッチし、$this->validate()
を使用するのと同じようにビューにエラーを提供します。
例をご覧ください。
use Illuminate\Support\Facades\Validator;
class ContactForm extends Component
{
public $email;
public function saveContact()
{
$validatedData = Validator::make(
['email' => $this->email],
['email' => 'required|email'],
['required' => 'The :attribute field is required'],
)->validate();
Contact::create($validatedData);
}
}
<div>
Email: <input wire:model.lazy="email">
@if($errors->has('email'))
<span>{{ $errors->first('email') }}</span>
@endif
<button wire:click="saveContact">Save Contact</button>
</div>
{note} Laravelの"FormRequest"を使用できるのかと疑問に思われるかもしれません。Livewireの性質上、httpリクエストにフックすることは意味がありません。現在のところ、この機能は使用できないか非推奨です。