*/ public function rules(): array { return [ 'variants' => ['required', 'array', 'min:1', 'max:1000'], 'variants.*' => ['required', 'array:id,type,sector,row,seat,price'], 'variants.*.id' => ['sometimes', 'integer', 'distinct'], 'variants.*.type' => ['required', 'string', 'max:100'], 'variants.*.sector' => ['required', 'string', 'max:100'], 'variants.*.row' => ['required', 'string', 'max:100'], 'variants.*.seat' => ['required', 'string', 'max:100'], 'variants.*.price' => ['required', 'numeric', 'min:0', 'max:99999999.99'], ]; } /** @return array */ public function after(): array { return [function (Validator $validator): void { $combinations = []; foreach ($this->input('variants', []) as $index => $variant) { if (! is_array($variant)) { continue; } $combination = collect(['type', 'sector', 'row', 'seat']) ->map(fn (string $field): string => mb_strtolower(trim((string) ($variant[$field] ?? '')))) ->implode('|'); if (isset($combinations[$combination])) { $validator->errors()->add( "variants.{$index}", 'La combinación de tipo, sector, fila y asiento no puede repetirse.', ); } $combinations[$combination] = true; } }]; } }