September 29, 2025

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

Tutorial
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.

Did you find this article helpful? Share it!