#Does Laravel have Model Validation?

31 messages · Page 1 of 1 (latest)

north hare
#

I'm pretty new to Laravel, coming from the Rails world.

In Rails validations are placed on the model. For example:

class User < ApplicationRecord
  validates :email, presence: true
end

This ensures that no matter how a User is created/edited (HTTP or otherwise) it always has an email.

Is there an equivalent pattern in Laravel?

zenith heart
north hare
#

that’s good to know. That was basic example. I’m thinking for more complex things like ensuring the email is an email, or that DOB isn’t in the future

vapid spear
#

It's quite comprehensive, I'm sure you'll find the validation rule you need for the fields of your Model.

#

And if not you can write custom validation rules.

north hare
#

Right, that’s fine I guess but it couples validation to requests instead of the model. If you were going to create instances outside of a request context then this doesn’t really make sense

vapid spear
#

Not sure if that's still maintained.

north hare
#

That looks interesting @vapid spear thanks!

My thought just now was that we could put only the rules on the model:

<?php

class Post
{
    static $rules = [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]
}

So that anywhere you're looking to use validate incoming data you can do:

Validator(some_data, Post::$rules)
vapid spear
north hare
#

Cool, good to know.

Is the convention just to use Request subclasses?

Again, I ask because I'm coming from Rails where–generally speaking–following the Rails conventions pays significant dividends in 99% of cases. In the 1% where it doesn't the conventions can be by-passed. I'm curious if the Laravel ecosystem has a similar thing going on.

vapid spear
#

Might be a slight issue if you want different types of validation on the same Model tho

#

My store and update functions on a User Model have different types of validation on some fields so I wouldn't be able to just define one set of rules.

north hare
#

That's interesting. Is that because you would expect everything to be there for create but not update?

vapid spear
#

But for a PUT it's a little different since I allow full objects on a PUT

#

And the User email can be in there

#

So it'll trip over the unique rule since it's already in the database when I created that User.

#

So I have to write a different type of unique rule for the email field.

#

Thus resulting in a CreateUserRequest and an UpdateUserRequest both with a different rule for the email field

north hare
#

Right, that makes sense. Makes me not want to put the rules on the model like I suggested.

Needing to do that is sort of a result of what the validation is happening too and why I find that convention a bit odd.

e.g. Rails has a uniqueness validator that knows how to handle both create and update.

class User < ApplicationRecord
  validates :email, presence: true, uniqueness: true
end

This works because it's not validating the request but actually the model.

Request validation is also a thing in Rails, it just serves a different purpose entirely.

But this isn't rails so I'll have to think about it more

vapid spear
#

Maybe there's someone that can chime in on Model validation that is not Request validation. I personally haven't encountered it yet in a Laravel project.

north hare
#

Yeah I'll keep looking around.

Like, an example I have is an "import roster" feature. You upload a CSV of student data and it creates a user for each row in the CSV.

The request validation would just be to check that the file was provided. The Model validation would not be associated with the request at all.

teal spire
#

Even though the examples always show the validation in the context of validating request input, you could use validators to validate other data. One approach you could try is to run a validator (using Validator::make) in a handler for the model's "saving" event, perhaps using $model->isDirty() to get the data to validate, or just use your rule definitions to figure out what fields to check. I linked the relevant sections of the Laravel docs, so you can see if those can accomplish what you're looking to do.

https://laravel.com/docs/10.x/validation#manually-creating-validators
https://laravel.com/docs/10.x/eloquent#events
https://laravel.com/docs/10.x/eloquent#examining-attribute-changes

Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.

Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.

misty moss
#

another way you could solve this:

class User {
    public function setEmailAttribute($value){
        // Check $value meets relevant criteria, otherwise throw exception  
    }
}
#

this is using Laravel's mutator as an opportunity to check the value being set to the email attribute

#

e.g. when you do $user->email = x

hoary otter
#

resoce