-
Notifications
You must be signed in to change notification settings - Fork 11.7k
[8.x] Conditionally merge validation rules #38373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
So in your example could you not have just used |
|
I've updated the example in the original comment with some additional conditions and attributes (I agree that adding just 1 attribute inside a The benefit for Below a more elaborate real-world example, chunks of a larger FormRequest (containing many more conditions). // Currently written as:
public function rules()
{
$rules = [
'details.download' => ['nullable', 'file'],
'groups' => ['array'],
'groups.*' => 'required|exists:groups,id',
];
if (Gate::allows('get-paid')) {
$rules['is_paid'] = 'required|boolean';
if ($this->boolean('is_paid')) {
$rules = array_merge($rules, [
'price' => 'nullable|numeric|min:1|required_without:subscriptions',
'subscriptions' => 'nullable|array',
'subscriptions.*' => 'required|exists:subscriptions,id'
]);
}
}
if(app(Plan::class)->id === 'free') {
$rules['details.download'][] = 'max:100000';
$rules['groups'][] = 'max:1';
}
return $rules;
}
// Could be written as this with Rule::mergeWhen()
public function rules()
{
return [
'details.download' => 'nullable|file',
'groups' => 'array',
'groups.*' => 'required|exists:groups,id',
Rule::mergeWhen(Gate::allows('get-paid'), [
'is_paid' => 'required|boolean',
Rule::mergeWhen(fn($input) => $input['is_paid'], [
'price' => 'nullable|numeric|min:1|required_without:subscriptions',
'subscriptions' => 'nullable|array',
'subscriptions.*' => 'required|exists:subscriptions,id'
]),
]),
Rule::mergeWhen(app(Plan::class)->id === 'free', [
'details.download' => 'max:100000',
'groups' => 'max:1',
]),
];
}
// Would have to be written as this with Rule::when().
public function rules()
{
// Gate::allows() and app(Plan::class) could be stored in a variable
// here, but doesn't necessarily improve readability of the method.
return [
'details.download' => [
'nullable',
'file',
Rule::when(app(Plan::class)->id === 'free', 'max:100000'),
],
'groups' => [
'array',
Rule::when(app(Plan::class)->id === 'free', 'max:1'),
],
'groups.*' => 'required|exists:groups,id',
'is_paid' => Rule::when(Gate::allows('get-paid'), 'required|boolean'),
'price' => Rule::when(fn($input) => Gate::allows('get-paid') && $input['is_paid'], 'nullable|numeric|min:1|required_without:subscriptions'),
'subscriptions' => Rule::when(fn($input) => Gate::allows('get-paid') && $input['is_paid'], 'nullable|array'),
'subscriptions.*' => Rule::when(fn($input) => Gate::allows('get-paid') && $input['is_paid'], 'required|exists:subscriptions,id'),
];
} |
|
I dunno, is it me or is the plain I can just look at one place to get all of the rules for a given attribute, instead of having to scan for merges. |
|
It's a subjective matter of preference I guess. Yes, the |
|
I think I'll hold off on this for now. |
Building upon the conditional rule support added in #38361, this PR adds support conditional rule merging through
Rule::mergeWhen(bool|callable $condition, array|callable $rules). Rules for attributes are merged, not overwritten, in the example belowstatewould be validated tostring, size:2, in:NY,CA,TX.