Installation:
composer require watson/validating
Add the trait to your Eloquent model:
use Watson\Validating\Validating;
class User extends Model
{
use Validating;
}
Define Validation Rules:
Override the rules() method in your model:
protected function rules()
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
];
}
First Use Case: Save a model instance—validation runs automatically:
$user = new User(['name' => 'John', 'email' => 'invalid-email']);
$saved = $user->save(); // Returns false if validation fails
rules(): Core method for defining validation rules.validate(): Manually trigger validation (returns true/false).validateOnly(): Validate specific fields without saving.errors(): Access validation error messages.Basic Validation on Save:
$user = new User(['email' => 'test@example.com']);
if ($user->save()) {
// Success: model saved
} else {
// Fail: errors available via $user->errors()
}
Dynamic Rules (Conditional Validation):
Use rules() with closures or override rules() dynamically:
protected function rules()
{
return [
'email' => function ($field) {
return $this->isAdmin()
? 'required|email'
: 'nullable|email';
},
];
}
Rule Sets (Multi-Validation Scenarios):
Define named rule sets in rules() and validate them explicitly:
protected function rules()
{
return [
'admin' => [
'email' => 'required|email',
'role' => 'in:admin,superadmin',
],
'user' => [
'email' => 'required|email',
],
];
}
// Validate 'admin' ruleset
$user->validate('admin');
Unique Validation with Model ID:
Automatically injects the model's ID into unique rules (e.g., unique:users,email,{$id}):
'email' => 'required|email|unique:users,email',
Custom Validation Logic: Extend the trait or use Laravel’s validation callbacks:
protected function validateCustomRules()
{
$this->validateCustom('password', function ($field) {
return strlen($field) >= 8;
}, 'Password must be at least 8 characters.');
}
FormRequest for API/controller validation.return response()->json(['errors' => $model->errors()], 422);
protected function onValidationFailed()
{
event(new ModelValidationFailed($this));
}
$user = new User(['email' => 'invalid']);
$user->shouldReceive('validate')->andReturn(false);
Rule Set Mismatches:
validate('ruleset').rules() and referenced correctly.Overriding save():
save() methods may bypass the trait’s validation.$this->validate() explicitly or use parent::save().Dynamic Rules Timing:
$this-> properties (e.g., $this->isAdmin()) may fail if accessed too early.Unique Rule ID Injection:
unique rules with dynamic IDs may fail if the model lacks an ID (e.g., during creation).unique:table,column,null,id,field for "ignore null" cases.Error Handling:
save() is called without checking its return value.$model->save() or use try-catch with exceptions:
try {
$model->save();
} catch (\Exception $e) {
// Handle validation exceptions
}
dd($this->getRules());
$validator = $this->getValidator(['field' => 'value']);
save() or validate().Custom Validation Logic:
Override validateCustomRules() to add field-specific checks.
Exception Handling: Extend the trait to throw custom exceptions:
protected function onValidationFailed()
{
throw new \InvalidArgumentException('Custom error message');
}
Rule Sets: Dynamically generate rule sets based on model state:
protected function rules()
{
return [
'active' => $this->isActive() ? ['field' => 'required'] : [],
];
}
Integration with Policies: Combine with Laravel’s authorization:
if ($this->authorize('update', $model)) {
$model->validate();
}
Mass Assignment:
Use fillable/guarded alongside validation to control allowed fields:
protected $fillable = ['name', 'email'];
How can I help you explore Laravel packages today?