Yii 2 如何在文件上传时添加自定义验证检查

Yii 2 How add a custom validation check on file upload

我正在构建一个 CSV 上传器,我想添加一个自定义验证函数来检查 CSV 文件的 header 行以确保正确的列就位。

我正在尝试在模型中放置一个自定义验证规则来执行此操作,但在第一个障碍上失败了。

我得到

Setting unknown property: yii\validators\FileValidator::0

例外,但据我从文档中可以看出这应该有效。

Model

/**
* UploadForm is the model behind the upload form.
*/
class UploadForm extends Model
{
/**
 * @var UploadedFile file attribute
 */
public $file;

/**
 * @return array the validation rules.
 */
public function rules()
{
    return [
        [['file'], 'file', 'extensions' => 'csv', 'checkExtensionByMimeType'=>false, 'headerCheck', 'skipOnEmpty' => false]
    ];
}

public function attributeLabels(){
    return [
        'file'=>'Select csv'
    ];
}

 function headerCheck($attribute, $params, $validato){

    $this->addError($attribute, "error");
}
}

Controller函数:

     public function actionUpload()
{
    $model = new UploadForm();

    if (Yii::$app->request->isPost) {
        $model->file = UploadedFile::getInstance($model, 'file');
        $filename = $model->file->baseName . '.' . $model->file->extension;

        if ($model->file && $model->validate()) {
            $upload = $model->file->saveAs('uploads/'.$filename );

            if($upload){
                define('CSV_PATH','uploads/');
                $csv_file = CSV_PATH . $filename;
                $filecsv = file($csv_file);

                foreach($filecsv as $data){
                    $lines = explode(',',$data);
                    $t=1;
                }
            }
        }
    }

    return $this->render('csvUpload', ['model' => $model]);
}

View

<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>

<?= $form->field($model, 'file')->fileInput() ?>

<button>Submit</button>

<?php ActiveForm::end() ?>

为什么 headerCheck() 没有被选为自定义验证函数?

简答

你的规则应该这样写:

return [
    [['file'], 'file', 'extensions' => 'csv', 'checkExtensionByMimeType'=>false, 'skipOnEmpty' => false],
    [["file"], "headerCheck"],
];

请注意,您的验证规则 "headerCheck" 是数组中的一个单独项目。

长答案

一个规则的结构是这样的:

[["attributes_to_validate"],"vaildatorCallback","param1"=>"value","param2"=>"value]

请注意前两项分别是属性和回调,然后您可以指定应分配给验证器或传递给验证器回调的参数。这些参数应以一种形式出现,其中键是 属性 的名称,值是分配给 属性.

的值

在您提供的示例中,Yii 发现您想要使用 "file" 验证器,因此它创建了一个 yii\validators\FileValidator 的实例。然后它看到您希望将参数 "extensions" 设置为 "csv",因此它执行了:yii\validators\FileValidator::$extensions = "csv"; 但是随后,因为您在数组的这一部分包含了自定义验证器,它认为"headerCheck" 实际上是要分配给验证器的 属性 的值。因为你输入的 "param" 没有键,键默认为 0 所以 Yii 认为你要分配的 属性 被称为'0'。因此,Yii 尝试这样做:yii\validators\FileValidator::0 = "headerCheck";

当然,FileValidator 上没有 属性 '0',所以这就是您收到的错误的来源。