Laravel Model Validation Package
The TL;DR
- I wrote a package that provides validation for Eloquent models.
- It allows you to define the foundational rules, messages, etc. for each model directly within your model classes.
- It has an opt-in feature to perform validation when saving.
- If you need to perform special validation at some point, for example when handling a particular request payload, it's easy to retrieve, extend, or replace the validation logic for a model.
- As of this moment, it's in an alpha release state. Feel free to give it a try, but note that the api may change slightly before it's v1.0 release.
Why use this package?
For a few main reasons:
- To reduce code duplication
- To reduce validation whoopsies
- To ensure data integrity when you can't control all of the times when your model will be filled/saved
Shouldn't validation be handled in Controllers or FormRequests?
Indeed, I think there are plenty of situations where validation needs to be performed in Controllers, FormRequests, and elsewhere (like Nova/Filament fields, console input, etc). However, after working with large applications containing over a hundred models and a ton of input vectors, I have found it's efficient and less buggy to define a foundational set of validation rules for each model and then handle extra validation concerns on a case by case basis wherever necessary.
Here are a few examples of putting that into practice.
- Sometimes, I will write a route to update a model record but I only want to permit the updating of certain attributes. In these situations, I will add the validation logic to my Controller or FormRequest class, but I will do so by grabbing the relevant rules from the model itself (
$requestRules = $model->validationRules('attribute_1', 'attribute_2', ...)
). By doing so, I can ensure that my$request->validated()
array only contains the attributes I want to update and that the rules for each attribute is correct (at least, as correct as I had previously defined within the model). - There are times when model attributes get a little messy and it can be easy to mistakenly fill a model in a database-valid-yet-logically-invalid way. Consider a hypothetical
Order
model withshipment_status
,tracking_number
,carrier
,shipped_at
, anddelivered_at
attributes (ok ok - we'd almost certainly want to break this out into related models but go with me for a second). As you can imagine, we may need various implementations to integrate withUPS
,USPS
,FedEx
,DHL
, etc and each would fill those variables. Note that our code has nothing to do with user input. Now, would it be possible to write one of these implementations and forget to fill an attribute or parse a date from the carrier's API incorrectly? Sure. Remember: handling validation for user input is essential, but programmers make mistakes too. In an ideal world, you'd have a test to cover yourself, but perhaps you had to rush out a feature and 100% code/state coverage wasn't possible. By defining some model validation rules, you could ensure that you never save a record when thedelivered_at
is before theshipped_at
, or have a record where thetracking_number
is filled but thecarrier
was leftnull
, or have acancelled
shipment_status
that left theshipped_at
filled. - When writing a package for others to use, you can't always control how the data will be filled for your packages' models. Thus, having validation at the model level helps to eliminate a footgun for the consumer of your package. If they write a custom admin form that deals with your models, you can be sure that they won't be able to (easily) save records that represent an invalid state.
Get started
Check out the repo and if you like the features & api described in the README, give it a try in your app.
composer require steven-fox/laravel-model-validation
I'm open to feedback and improvements.