Skip to content

Conversation

@lucasacoutinho
Copy link

When writing custom validation rules for array items, accessing sibling data requires manual path manipulation. Consider an API for bulk order creation:

{ "orders": [ { "customer_id": 123, "items": [ { "product_id": 1, "quantity": 10, "unit_price": 150.00, "discount": 2000.00 } ] } ] } 

To validate that discount doesn't exceed the line total (quantity x unit_price), you currently need:

class DiscountMustNotExceedLineTotal 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 { // $attribute = "orders.0.items.1.discount" // Need to extract indices and navigate the nested structure preg_match('/^orders\.(\d+)\.items\.(\d+)\./', $attribute, $matches); $orderIndex = $matches[1] ?? null; $itemIndex = $matches[2] ?? null; if ($orderIndex === null || $itemIndex === null) { return; } $item = $this->data['orders'][$orderIndex]['items'][$itemIndex] ?? []; $lineTotal = ($item['quantity'] ?? 0) * ($item['unit_price'] ?? 0); if ($value > $lineTotal) { $fail("The discount cannot exceed the line total of {$lineTotal}."); } } }

We could make the experience much nicer with a new and more limited ScopeAwareRule interface that automatically receives the current array item's data:

class DiscountMustNotExceedLineTotal implements ValidationRule, ScopeAwareRule { protected array $scope = []; public function setScope(array $scope): static { $this->scope = $scope; return $this; } public function validate(string $attribute, mixed $value, Closure $fail): void { $lineTotal = ($this->scope['quantity'] ?? 0) * ($this->scope['unit_price'] ?? 0); if ($value > $lineTotal) { $fail("The discount cannot exceed the line total of {$lineTotal}."); } } }
@lucasacoutinho lucasacoutinho marked this pull request as draft December 10, 2025 23:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant