Как я понял, единственно возможное решение - сделать это в два этапа:
$this->validate($request, [
'categories' => 'required|array',
'categories.*.name' => 'required_without:categories.*.isGeneral|string|max:255',
'categories.*.fields' => 'required|array',
'categories.*.fields.*.name' => 'required|string',
'categories.*.fields.*.type' => 'required|in:numbers,dates',
'categories.*.fields.*.rules' => 'required|array',
]);
$dateFields = [];
$numberFields = [];
foreach ($request->post('categories') as $categoryIndex => $category) {
$dateFields[$categoryIndex] = ['fields' => []];
$numberFields[$categoryIndex] = ['fields' => []];
foreach ($category['fields'] as $fieldIndex => $field) {
if ($field['type'] === 'numbers') {
$numberFields[$categoryIndex]['fields'][$fieldIndex] = $field;
} else if ($field['type'] === 'dates') {
$dateFields[$categoryIndex]['fields'][$fieldIndex] = $field;
}
}
}
$dateFieldsValidator = $this->getValidationFactory()->make($dateFields, [
'*.fields.*.rules.*.from' => 'required|date',
'*.fields.*.rules.*.to' => 'required|date|gte:*.fields.*.rules.*.from',
'*.fields.*.rules.*.rate' => 'required|numeric|between:0,100',
]);
$numberFieldsValidator = $this->getValidationFactory()->make($numberFields, [
'*.fields.*.rules.*.from' => 'required|numeric',
'*.fields.*.rules.*.to' => 'required|numeric|gte:*.fields.*.rules.*.from',
'*.fields.*.rules.*.rate' => 'required|numeric|between:0,100',
]);
$errors = [];
if ($dateFieldsValidator->fails()) {
$errors = array_merge($errors, $dateFieldsValidator->errors()->getMessages());
}
if ($numberFieldsValidator->fails()) {
$errors = array_merge($errors, $numberFieldsValidator->errors()->getMessages());
}