Laravel’s `DataAwareRule`: Smarter Cross-Field Validation

Custom validation rules in Laravel can only see the single field they’re validating. But what if you need to check multiple fields together, like making sure two numbers add up to a limit, or a discount doesn’t exceed a product’s price?
That’s where Illuminate\Contracts\Validation\DataAwareRule
comes in. This contract lets your rule class access the entire data set being validated by automatically injecting it through a setData()
method.
Example 1: Ensuring a Discount Doesn’t Exceed Price
Imagine an online store where you want to ensure that discount_price
is never greater than original_price
.
namespace App\Rules; use Closure; use Illuminate\Contracts\Validation\DataAwareRule; use Illuminate\Contracts\Validation\ValidationRule; class ValidDiscount implements ValidationRule, DataAwareRule { protected array $data = []; public function setData(array $data): static { $this->data = $data; return $this; } public function validate(string $attribute, mixed $value, Closure $fail): void { $original = $this->data['original_price'] ?? null; if ($original !== null && $value > $original) { $fail('The discount price cannot be greater than the original price.'); } } }
Usage in your form request or controller:
$request->validate([ 'original_price' => ['required','numeric','min:1'], 'discount_price' => ['nullable','numeric','min:0', new ValidDiscount], ]);
Now, whenever you validate a product, the ValidDiscount
rule can see both fields and enforce the business rule.
Example 2: Age Restriction Based on Role
Suppose you’re building a registration form. If a user selects role = driver
, their age
must be at least 18.
namespace App\Rules; use Closure; use Illuminate\Contracts\Validation\DataAwareRule; use Illuminate\Contracts\Validation\ValidationRule; class AgeRequirement implements ValidationRule, DataAwareRule { protected array $data = []; public function setData(array $data): static { $this->data = $data; return $this; } public function validate(string $attribute, mixed $value, Closure $fail): void { $role = $this->data['role'] ?? null; if ($role === 'driver' && (int) $value < 18) { $fail('Drivers must be at least 18 years old.'); } } }
Validation example:
$request->validate([ 'role' => ['required', 'string'], 'age' => ['required', 'integer', new AgeRequirement], ]);
This way, the AgeRequirement
rule doesn’t just validate age
in isolation — it also considers the role
field.
When to Reach for DataAwareRule
Use DataAwareRule
when:
- Validation depends on multiple fields.
- You need business logic inside a reusable rule class, not scattered across controllers.
- You want cleaner, testable rules for complex validation.
It’s a small feature, but it makes custom rules much more powerful and expressive.