Yii2中已上传文件,fileInput仍提示必填的问题求助
解决Yii2文件上传字段必填验证错误问题
在Yii2项目中配置了两个必填的fileInput字段,即便已选择并上传文件,提交时仍会弹出必填错误提示。

相关代码片段
View
<?php $form = ActiveForm::begin([ 'enableAjaxValidation' => true, 'enableClientValidation' => false, 'options'=>['enctype'=>'multipart/form-data']]); ?> <div class="div_salary_deposited"> <div class="row"> <div class="col-lg-4 col-md-4 col-sm-4"> <div class="form-group"> <label class="control-label">Scan copy of Payslip: <span class="required">*</span></label> <?= $form->field($modelPlacementTrackingSalaryInformation, 'scan_copy_of_payslip')->label(false)->fileInput() ?> </div> </div> <div class="col-lg-4 col-md-4 col-sm-4"> <div class="form-group"> <label class="control-label">Salary Payment Proof: <span class="required">*</span></label> <?= $form->field($modelPlacementTrackingSalaryInformation, 'salary_payment_proof')->label(false)->fileInput() ?> </div> </div> </div> </div> <div class="form-group"> <ul class="list-unstyled list-inline"> <li> <button class="btn btn-info" type="submit">Continue</button> </li> </ul> </div> <div class="clearfix"></div> <?php ActiveForm::end(); ?>
Controller
/* salary-information */ public function actionSalaryInformation(){ $modelPlacementTrackingSalaryInformation = $this->placementTrackingRepository->getPlacementTrackingSalaryInformationModel(); $modelPlacementTrackingSalaryInformation->placement_tracking_id = $placement_tracking_id; if(($postData = Yii::$app->request->post()) && !empty($postData) && $modelPlacementTrackingSalaryInformation->load($postData)){ if(Yii::$app->request->isAjax){ Yii::$app->response->format = Response::FORMAT_JSON; return ActiveForm::validate($modelPlacementTrackingSalaryInformation); } } return $this->render('salary_information',[ 'modelPlacementTrackingSalaryInformation' => $modelPlacementTrackingSalaryInformation, ]); }
Model
<?php namespace app\models; use Yii; class PlacementTrackingCandidateSalaryInfo extends \yii\db\ActiveRecord { public $salaryFrom; public $salaryTo; public function rules() { return [ ['placement_tracking_id','required','message' => 'Placement Tracking Id missing'], ['salary_deposited','required','message' => "Please select 'Salary deposited?'"], /* START: Is Salary Deposited: Yes */ //Bank Name ['bank_name', 'required', 'when' => function($model){ return ($model->salary_deposited == '1') ? true : false; },'message' => "Please select 'Bank Name'."], //Branch Name ['branch_name', 'required', 'when' => function($model){ return ($model->salary_deposited == '1') ? true : false; },'message' => "Please enter 'Branch Name'."], //Salary ['salary', 'required', 'when' => function($model){ return ($model->salary_deposited == '1') ? true : false; },'message' => "Please enter 'Salary'."], //Salary From Date ['salaryFrom', 'required', 'when' => function($model){ return ($model->salary_deposited == '1') ? true : false; },'message' => "Please select 'Salary From Date'."], //Salary To Date ['salaryTo', 'required', 'when' => function($model){ return ($model->salary_deposited == '1') ? true : false; },'message' => "Please select 'Salary To Date'."], //No of Days ['no_of_days', 'required', 'when' => function($model){ return ($model->salary_deposited == '1') ? true : false; },'message' => "Please enter 'No of Days'."], //Reference No ['reference_no', 'required', 'when' => function($model){ return ($model->salary_deposited == '1') ? true : false; },'message' => "Please enter 'Reference Number'."], //Scan Copy of Payslip ['scan_copy_of_payslip', 'required', 'when' => function($model){ return ($model->salary_deposited == '1') ? true : false; },'message' => "Please upload 'Scan Copy of Payslip'."], //Salary Payment Proof ['salary_payment_proof', 'required', 'when' => function($model){ return ($model->salary_deposited == '1') ? true : false; },'message' => "Please upload 'Salary Payment Proof'."], /* END: Is Salary Deposited: Yes */ [['salary_from_month','salary_from_year','salary_to_month','salary_to_year'],'safe'], ]; } }
问题原因及解决方案
问题根源
启用Ajax验证时,上传文件不会通过POST参数传递,而是存储在$_FILES数组中,但$model->load($postData)仅会加载POST数据,不会自动处理上传文件,导致模型的文件字段为空,触发必填验证错误。
解决方案步骤
修改Controller,手动加载上传文件到模型
在Ajax验证分支中,使用UploadedFile::getInstance()将文件对象赋值给模型字段,确保验证时能识别到已上传的文件:// 引入UploadedFile类 use yii\web\UploadedFile; /* salary-information */ public function actionSalaryInformation(){ $modelPlacementTrackingSalaryInformation = $this->placementTrackingRepository->getPlacementTrackingSalaryInformationModel(); $modelPlacementTrackingSalaryInformation->placement_tracking_id = $placement_tracking_id; if(($postData = Yii::$app->request->post()) && !empty($postData) && $modelPlacementTrackingSalaryInformation->load($postData)){ if(Yii::$app->request->isAjax){ // 手动加载上传的文件到模型 $modelPlacementTrackingSalaryInformation->scan_copy_of_payslip = UploadedFile::getInstance($modelPlacementTrackingSalaryInformation, 'scan_copy_of_payslip'); $modelPlacementTrackingSalaryInformation->salary_payment_proof = UploadedFile::getInstance($modelPlacementTrackingSalaryInformation, 'salary_payment_proof'); Yii::$app->response->format = Response::FORMAT_JSON; return ActiveForm::validate($modelPlacementTrackingSalaryInformation); } } return $this->render('salary_information',[ 'modelPlacementTrackingSalaryInformation' => $modelPlacementTrackingSalaryInformation, ]); }完善Model的文件验证规则
在模型规则中添加文件格式、大小验证,确保上传文件符合要求,同时保留必填规则:// 在现有规则后添加 ['scan_copy_of_payslip', 'file', 'extensions' => 'png,jpg,pdf', 'maxSize' => 1024*1024*5, 'when' => function($model){ return $model->salary_deposited == '1'; }, 'message' => '请上传有效的图片或PDF文件,大小不超过5MB'], ['salary_payment_proof', 'file', 'extensions' => 'png,jpg,pdf', 'maxSize' => 1024*1024*5, 'when' => function($model){ return $model->salary_deposited == '1'; }, 'message' => '请上传有效的图片或PDF文件,大小不超过5MB'],可选:跳过文件字段的Ajax验证
如果不需要对文件字段进行实时Ajax验证,可以在模型的必填规则中添加enableAjaxValidation => false,仅在表单提交时验证文件:['scan_copy_of_payslip', 'required', 'when' => function($model){ return $model->salary_deposited == '1'; }, 'message' => "Please upload 'Scan Copy of Payslip'.", 'enableAjaxValidation' => false],
内容的提问来源于stack exchange,提问作者Nana Partykar
相关产品推荐
相关产品推荐

