如何在Yii 2中的更新操作上实现所需的文件上载属性?

时间:2016-05-19 10:47:14

标签: validation file-upload yii2 modelform filehelpers

我需要创建和更新操作所需的文件上载字段,以及在两种情况下都要执行的类型的必需验证和验证。

这就是我的表单的样子(注意:这是一个表单,而不是Active Record模型):

<?php

namespace app\models;

use Yii;
use yii\base\Model;
use yii\base\Object;
use yii\helpers\FileHelper;

class MyCustomForm extends Model
{

    public $file_image;

    public function rules()
    {
        return [
            [
                [['file_image'], 'file', 'skipOnEmpty' => false, 'extensions' => 'jpg, jpeg, png, bmp, jpe']
            ]
        ];
    }

    public function scenarios()
    {
        $scenarios = parent::scenarios();
        //Scenarios Attributes that will be validated
        $scenarios['action_add'] = ['file_image'];
        $scenarios['action_edit'] = ['file_image'];
        return $scenarios;
    }
}

这就是我的控制器动作的样子。

Create操作按预期工作(在POST请求中我使用UploadedFile :: getInstance命令上传文件)

public function actionCreate()
{
    $model_form = new MyCustomForm(['scenario' => 'action_add']);
    if (Yii::$app->request->isPost && $model_form->load(Yii::$app->request->post())) {
        $model_form->file_image = \yii\web\UploadedFile::getInstance($model_form, "file_image");
        if($model_form->validate()) {
            if(isset($model_form->file_image)){
                //I'm uploading my image to some cloud server here

                //creating corresponding $model_entity for database, fill with the data from the form and save it
                $model_entity->save();
            }
        }
    }
}

但是在Update操作中执行相同操作时我遇到了一个问题。在数据库中我有第三方云服务器上的图像的URL,我可以访问它并以我的形式显示图像(因此更新上的GET请求工作,我从数据库获取相应的实体并用数据填充表单)。但对于POST,文件验证失败,如果我没有在模型中分配文件,并且POST的Update请求不起作用。

public function actionUpdate($id)
{
    $model_entity = $this->findModel($id);        

    $image_URL = //I'm having URL to corresponding image here;

    $model_form = new MyCustomForm(['scenario' => 'action_edit']);        
    $model_form_data = [$model_form->formName() => $model_entity->attributes];
    $model_form->load($model_form_data); 

    if (Yii::$app->request->isPost && $model_form->load(Yii::$app->request->post())) {
        //if we upload image again this will work
        //NOTE: I have another text fields in the form and If I only change them
        //and if I don't change the file image, the following result will return NULL and validation will fail
        $file_uploaded_image = \yii\web\UploadedFile::getInstance($model_form, "file_image");

        if(isset($file_uploaded_image)){
            //new image is uploaded on update, this scenario will be OK
        } else {
            //no image is uploaded on update, this scenario will fail
        }

       if($model_form->validate()) {
           //this will fail if I don't upload image on Update
       }

    }

}

我在验证之前在Update操作中尝试了很多东西,以便找到一种解决方法,以使图像和验证不会失败。例如:

$dataImg = file_get_contents($image_URL);
$model_form->file_image = $dataImg;

或尝试使用临时文件:

$dataImg = file_get_contents($dataImg);
$filePath = \yii\helpers\FileHelper::createDirectory("/images/tmp/test.png", 777);
file_put_contents($filePath, $dataImg);
$model_form->file_image = $filePath;

但他们都没有工作。这个场景有什么解决方案吗? 请注意,我将不得不使用Froms(如上所述)而不是ActiveRecord,因为我的真实项目比列出的示例更复杂。

1 个答案:

答案 0 :(得分:0)

将此代码写入模型(MyCustomForm)

class MyCustomForm extends Model
{

    public $file_image;

    public function rules()
    {
        return [
            [['file_image',],'required','on'=>['create','update']],
            [['file_image'], 'file','extensions' => 'jpg, jpeg, png, bmp, jpe'],
        ];
    }
}

将此代码写入 actionCreate ():

$model_form = new MyCustomForm();
$model_form->scenario = "create";

将此代码写入 actionUpdate ():

$model_form = new MyCustomForm();
$model_form->scenario = "update";

或者您可以通过以下方式添加方案

$model_form = new MyCustomForm(['scenario' => 'create']);

我试过这个并且它正在运作。