Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

troccoli's avatar

Do I need `$this->validate()` if I use the `Validate` attribute for my properties?

I have a simple Livewire component to sign the user in

class SignIn extends Component
{
    #[Validate('required|email')]
    public string $email = '';

    #[Validate('required|string')]
    public string $password = '';

    public function submit(AuthenticationService $authenticationService): void
    {
        $this->validate();

        try {
            $authenticationService->signInWithUsernamePassword(
                username: $this->email,
                password: $this->password,
            );

            $this->redirectIntended(default: route('home'));
        } catch (InvalidCredentials) {
            // error handling
        }
    }

I wrote some tests for it and I am now trying to introduce mutation testing. The mutation testing fails (i.e. my tests still pass) when the call to $this->validate() is removed.

I do have tests for validation, for example

it('needs a valid email address', function (): void {
    Livewire::test(SignIn::class)
        ->set('email', '')
        ->call('submit')
        ->assertHasErrors(['email' => 'The email field is required.'])
        ->set('email', 'myemail')
        ->call('submit')
        ->assertHasErrors(['email' => 'The email field must be a valid email address.']);
});

Since I use the Validate attribute I thought that was enough and tried to remove the call to $this->validate(). All tests still pass, and the mutation testing passes too. All good then, right?

Well, not quite. Because then I wondered: why do we have the validate() method? I understand its use when not using the attribute, but even the documentation says

By associating validation rules with properties using #[Validate], Livewire will automatically run the properties validation rules before each update. However, you should still run $this->validate() before persisting data to a database so that properties that haven't been updated are also validated.

I'm quite confused now. Do I need to call $this->validate() in my submit() method? If I do, how can I write a test that would fail if the call to $this->validate() is removed (by the Pest mutator)?

0 likes
1 reply
LaryAI's avatar

Great question! Let’s clarify how Livewire’s #[Validate] attribute and the $this->validate() method interact, and how you can test for their necessity.

1. What does #[Validate] do?

When you use the #[Validate] attribute on a property, Livewire will automatically validate that property when it is updated (e.g., when the user types in an input bound to that property). This is called "field-level validation" or "on update validation".

However:
This automatic validation only runs for properties that are being updated. If a property is never updated by the user (e.g., a hidden field, or one not present in the form), its validation rule is not enforced unless you call $this->validate() manually.

2. What does $this->validate() do?

Calling $this->validate() in your action method (like submit()) will validate all properties with validation rules, regardless of whether they were updated or not. This is essential before you perform critical actions like authentication or saving to the database.

3. Should you call $this->validate() in submit()?

Yes, you should!
Even with #[Validate] attributes, you should call $this->validate() in your submit() method to ensure all validation rules are enforced at the time of submission, not just those that were updated.

4. Why do your tests still pass if you remove $this->validate()?

Your current tests only check for validation errors when you set the property and call submit(). Since Livewire validates on update, the errors are triggered as expected.

However, if you want to ensure that $this->validate() is necessary, you need to test the scenario where a property is never updated, but still required.

5. How can you write a test that fails if $this->validate() is removed?

Write a test where you do not set one of the required properties before calling submit(). For example, don’t set the password property:

it('requires a password even if not updated', function () {
    Livewire::test(SignIn::class)
        ->set('email', '[email protected]')
        ->call('submit')
        ->assertHasErrors(['password' => 'required']);
});

If you remove $this->validate() from submit(), this test will fail (i.e., it will not catch the missing password), because Livewire only validates properties on update unless you call $this->validate().


Summary

  • Always call $this->validate() in your submit methods to ensure all rules are enforced.
  • The #[Validate] attribute only validates on property update.
  • To test the necessity of $this->validate(), write a test where you do not set all required properties before submission.

References:

Let me know if you’d like more examples or clarification!

Please or to participate in this conversation.