route('modelId'); $parameterId = $this->route('parameterId'); $rules = [ 'parameter_name' => [ 'required', 'string', 'max:50', 'regex:/^[a-zA-Z][a-zA-Z0-9_]*$/', Rule::unique('model_parameters') ->where('model_id', $modelId) ->where('tenant_id', auth()->user()?->currentTenant?->id) ->whereNull('deleted_at') ], 'parameter_type' => ['required', 'string', 'in:INPUT,OUTPUT'], 'is_required' => ['boolean'], 'default_value' => ['nullable', 'string', 'max:255'], 'min_value' => ['nullable', 'numeric'], 'max_value' => ['nullable', 'numeric', 'gte:min_value'], 'unit' => ['nullable', 'string', 'max:20'], 'options' => ['nullable', 'array'], 'options.*' => ['string', 'max:100'], 'description' => ['nullable', 'string', 'max:500'], 'sort_order' => ['integer', 'min:0'], ]; // For update requests, ignore current record in unique validation if ($parameterId) { $rules['parameter_name'][4] = $rules['parameter_name'][4]->ignore($parameterId); } return $rules; } /** * Get custom messages for validator errors. */ public function messages(): array { return [ 'parameter_name.required' => '매개변수 이름은 필수입니다.', 'parameter_name.regex' => '매개변수 이름은 영문자로 시작하고 영문자, 숫자, 언더스코어만 사용할 수 있습니다.', 'parameter_name.unique' => '해당 모델에 이미 동일한 매개변수 이름이 존재합니다.', 'parameter_type.required' => '매개변수 타입은 필수입니다.', 'parameter_type.in' => '매개변수 타입은 INPUT 또는 OUTPUT이어야 합니다.', 'min_value.numeric' => '최소값은 숫자여야 합니다.', 'max_value.numeric' => '최대값은 숫자여야 합니다.', 'max_value.gte' => '최대값은 최소값보다 크거나 같아야 합니다.', 'unit.max' => '단위는 20자를 초과할 수 없습니다.', 'description.max' => '설명은 500자를 초과할 수 없습니다.', 'sort_order.min' => '정렬 순서는 0 이상이어야 합니다.', ]; } /** * Get custom attribute names for validator errors. */ public function attributes(): array { return [ 'parameter_name' => '매개변수 이름', 'parameter_type' => '매개변수 타입', 'is_required' => '필수 여부', 'default_value' => '기본값', 'min_value' => '최소값', 'max_value' => '최대값', 'unit' => '단위', 'options' => '옵션 목록', 'description' => '설명', 'sort_order' => '정렬 순서', ]; } /** * Prepare the data for validation. */ protected function prepareForValidation(): void { $this->merge([ 'is_required' => $this->boolean('is_required', false), 'sort_order' => $this->integer('sort_order', 0), ]); // Convert options to array if it's a string if ($this->has('options') && is_string($this->input('options'))) { $options = json_decode($this->input('options'), true); if (json_last_error() === JSON_ERROR_NONE) { $this->merge(['options' => $options]); } } } /** * Configure the validator instance. */ public function withValidator($validator) { $validator->after(function ($validator) { // Validate that INPUT parameters can have default values and constraints if ($this->input('parameter_type') === 'INPUT') { $this->validateInputParameterConstraints($validator); } // Validate that OUTPUT parameters don't have input-specific fields if ($this->input('parameter_type') === 'OUTPUT') { $this->validateOutputParameterConstraints($validator); } // Validate min/max value relationship $this->validateMinMaxValues($validator); }); } /** * Validate INPUT parameter specific constraints. */ private function validateInputParameterConstraints($validator): void { // INPUT parameters can have all constraints // No additional validation needed for INPUT type } /** * Validate OUTPUT parameter specific constraints. */ private function validateOutputParameterConstraints($validator): void { // OUTPUT parameters should not have certain input-specific fields if ($this->filled('is_required') && $this->input('is_required')) { $validator->errors()->add('is_required', 'OUTPUT 매개변수는 필수 항목이 될 수 없습니다.'); } if ($this->filled('default_value')) { $validator->errors()->add('default_value', 'OUTPUT 매개변수는 기본값을 가질 수 없습니다.'); } } /** * Validate min/max value relationship. */ private function validateMinMaxValues($validator): void { $minValue = $this->input('min_value'); $maxValue = $this->input('max_value'); if ($minValue !== null && $maxValue !== null && $minValue > $maxValue) { $validator->errors()->add('max_value', '최대값은 최소값보다 크거나 같아야 합니다.'); } } }