To validate a field only if another passes validation, there are multiple solutions.
Approach #2 (recommended)
Since Laravel 5.3.23; Simply move any field validation that depends on another field's rules, into Controller's withValidator(...) method, like:
use Illuminate\Support\Facades\Validator;
// ...
public function withValidator($validator)
{
$validator->after(function ($validator) {
// Skip if any previous field was invalid.
if ($validator->failed()) return;
// Actual validation (for fields depending on previous).
Validator::make($this->input(), [
'warehouse_qty' => ['required']
])->validate();
});
}
This has the advantage of simply using existing rules, as you would normally (instead of rewriting the "required" rule's source-code, which the below approach does).
See also related Laracast post.
Note that if rules() method is not defined,
withValidator(...) is never called (and calling $this->input() may result in function not defined error).
Approach #1 (Old answer)
Since Laravel 5.6 and later we can do below:
use Illuminate\Support\Facades\Validator;
// ...
public function rules()
{
$result = [
// ...
'warehouse_id' => 'required|unique:warehouse,id',
];
if (Validator::make($this->input(), $result)->passes()) {
$result['warehouse_qty'] = [
function ($attribute, $value, $fail) {
if (empty($value)) {
$fail('The '.$attribute.' is required.');
}
},
];
}
return $result;
}
Note that for above to work, the fields order is important, and the closure should be added to array right after the fields it is depending on.
-------===-------
While above are custom approaches (for asked matter), doing that for rules of the same field is built-in Laravel.
- Adding a rule if another rule passed is easy:
- The rules are executed from left to right.
- Use pipe (the
| character) to separate rules.
- And, as long as rules at left pass, the later rules are added and/or executed.
- Removing a rule if another rule fails can be achieved by pipe as well.
Simply because any rule after the failed one is ignored.
- But the reverse of above two statements is not possible:
- We can not add and/or execute next-rule if previous fails.
- We can not remove next-rule if previous passed.
- At least, not without custom function.