You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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数据,不会自动处理上传文件,导致模型的文件字段为空,触发必填验证错误。

解决方案步骤

  1. 修改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,
        ]);
    }
    
  2. 完善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'],
    
  3. 可选:跳过文件字段的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:20:55