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

naykel's avatar

Livewire 3: Leveraging Validation for Cleaner Code

Since Livewire 3 removed binding directly to Eloquent models, I have struggled to wrap my head around the amount of work to individually handle each property. I am aware that I can enable legacy_model_binding but I would like to embrace the new way of doing things.

In this example, only the name property will run through the validator.

class CourseForm extends Form
{
    public Course $course;

    #[Validate('required|max:255')]
    public string $name;
    public string $code;
    public string $description;

    public function setModel(Course $course) {
        $this->course = $course;
        $this->name = $this->course->name ?? '';
        $this->code = $this->course->code ?? '';
        $this->description = $this->course->description ?? '';
    }

    public function update(){
        $this->validate();
        $this->course->name = $this->name;
        $this->course->code = $this->code;
        $this->course->description = $this->description;
        $this->course->save();
    }
}

Since the validation method returns an array of validated properties, I was thinking i could leverage this and add #[Validate('sometimes')] to the properties that are not required which will add the property to the validated array.

This creates a cleaner and more readable code, but I need to make sure there is no unintended consequences of doing this.

In this example all properties will run through the validator and be returned in the validated array.

class CourseForm extends Form
{
    public Course $course;

    #[Validate('required|max:255')]
    public string $name;
    #[Validate('sometimes')]
    public string $code;
    #[Validate('sometimes')]
    public string $description;

    public function setModel(Course $course) {
        $this->course = $course;
        $this->name = $this->course->name ?? '';
        $this->code = $this->course->code ?? '';
        $this->description = $this->course->description ?? '';
    }

    public function update(){
        $validated = $this->validate();
        $this->course->update([$validated]);
    }
}

Any feedback is most welcome.

0 likes
1 reply
LaryAI's avatar
Level 58

The approach you're considering, using the #[Validate] attribute for each property and leveraging the validate() method to return an array of validated properties, is indeed a cleaner way to handle validation in Livewire 3. By using the sometimes rule, you're indicating that the field should only be validated if it is present in the input data, which can be useful for optional fields.

However, there are a few considerations to keep in mind:

  1. Mass Assignment: When you pass the $validated array directly to the update method, you're assuming that all the fields in the $validated array are fillable on the model. Make sure that your Course model has the appropriate $fillable or $guarded properties set to prevent mass-assignment vulnerabilities.

  2. Validation Rules: Ensure that your validation rules are comprehensive and cover all the cases for your fields. For example, if code and description are optional but have specific requirements when they are present, you should include those rules in the #[Validate] attribute.

  3. Unintended Data Overwrite: If you have default values or computed properties on your model that should not be overwritten by null values when not present in the request, you need to handle this in your code. The sometimes rule will skip validation for these fields if they are not present, but if they are null in the request, they will still be included in the $validated array and potentially overwrite existing values.

Here's an updated version of your update method that takes these considerations into account:

public function update(){
    $validated = $this->validate();

    // Filter out null values if you don't want to overwrite existing values with null
    $validated = array_filter($validated, function ($value) {
        return !is_null($value);
    });

    // Update the model with the validated data
    $this->course->update($validated);
}

By using array_filter, you can remove any null values from the $validated array before passing it to the update method. This prevents overwriting fields with null if they are not present in the input data. Adjust the array_filter callback as needed based on your specific requirements.

Remember to test your code thoroughly to ensure that it behaves as expected, especially with optional fields and default values.

Please or to participate in this conversation.