restrict validation to checking the inputs (form or api) and check the product_id in the controller or otherwise.?
Validate a field only if another one passes validation
I have a form request that needs to validate 2 fields. However, I need to validate one of the fields only if the other one passes validation. I came up with something like this:
public function rules()
{
return [
'token' => ['bail', 'required', 'uuid', new ValidExchange],
];
}
public function withValidator($validator)
{
$validator->after(function ($validator) {
// This forces the validator to evaluate the rules defined in the rules() method above.
if ($validator->failed()) return;
// We only want to validate this field if the `token` rules were successful.
// The `ValidExchange` injects the `product_id` into the request object, making it
// available here, while IT IS NOT in the rules() method.
// The `product_id` is known to us only after the `ValidExchange` rule is evaluated!
Validator::make($this->input(), [
'product_id' => ['required', new NoUnusedCards(auth()->id())]
])->validate();
});
}
As the comment in the code says, the ValidExchange rule performs an API call to some external service, which returns an id that can be used to find a row in the database locally, from which we can get the product_id and inject it into the request object as follows:
request()->merge(['product_id' => $card->product_id]);
, as it too needs to be validated.
This works but doesn't feel right. Is there a cleaner way to do this or another approach that I might be missing? Thank you :)
@uhajzeraj withValidator is specifically designed to use the after hook. Basically to run validation after other validation. This is probably the exact correct pattern for what you are doing. This exists in the Laravel docs.
See: Adding After Hooks to Form Requests (Just below this section)
https://laravel.com/docs/6.x/validation#creating-form-requests
Please or to participate in this conversation.