1

I have problem with upload file. I use kartik-v/yii2-widget-fileinput extension. Here my code:

form model rule

/**
 * @inheritdoc
 */
public function rules()
{
    return [
        [['image'], 'required', 'on' => static::SCENARIO_CREATE],
        [['image'], 'file', 'extensions' => 'png, jpg, jpeg', 'maxSize' => 1024 * 1024],
    ];
}

form view

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

 <?= $form->field($model, 'image')->widget(FileInput::classname(), [
            'options' => ['accept' => 'image/*'],
            'pluginOptions' => [
                'showPreview' => false,
                'showCaption' => true,
                'showRemove' => true,
                'showUpload' => false,
                'showCancel' => false
            ],            
        ]); ?>

controller action

 public function actionCreate()
{
    $model = new ItemForm();
    $model->scenario = ItemForm::SCENARIO_CREATE;

    if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
        Yii::$app->response->format = Response::FORMAT_JSON;
        return ActiveForm::validate($model);
    }

    if ($model->load(Yii::$app->request->post())) {

        $image = UploadedFile::getInstance($model, 'image');

        $randomString = Yii::$app->getSecurity()->generateRandomString(10);
        $name = Inflector::slug($model->title) . '_' . $randomString . '.' . $image->extension;

        $url = Image::URL . $name;

        $model->image = $name;          

        if ($model->save()) {
            $image->saveAs($url);
            return $this->redirect(['view', 'id' => $model->id]);
        }       
    } else {         
        return $this->render('create', [
            'model' => $model,             
        ]);
    }
}

Always when I submit form, I got error "image field is required". I have read many tutorials but still I have the same problem when I using ajax validation. Can anyone look at it and tell me what I'm doing wrong?

1
  • i added an answer see if that helps you out Commented Jan 8, 2018 at 22:55

1 Answer 1

3

EDIT

Above all you should not use enableAjaxValidation option if you have a file type field in your form. see this ISSUE use enableClientValidation instead

Apart from that looking at your complete model it looks like you are trying to use the database table field image as the same field to upload images where as you should not do that you should declare a custom field inside your model and use it to upload the file and assign the new filename to the database field image currently you have to do some additions in your model and changes to the code

1. Declare a custom field with the name $file like below on top of your model after public $tags like this, public $myFile;

2. Change your validation rule

[['image'], 'file', 'extensions' => 'png, jpg, jpeg', 'maxSize' => 1024 * 1024],

to the following

[['myFile'], 'file', 'extensions' => 'png, jpg, jpeg', 'maxSize' => 1024 * 1024],

and

[['image'], 'required', 'on' => static::SCENARIO_CREATE],

to this

[['myFile','image'], 'required', 'on' => static::SCENARIO_CREATE],

3. Change your field name in the html form, from image to myFile i.e $form->field($model, 'image') to $form->field($model, 'myFile').

4. For changes inside the action and uploadItemImage() function see below i have updated them.


you are assigning the $name variable to the $model->image field

 $model->image = $name; 

and in the $name it is a string, whereas in the model it should be a file

 $name = Inflector::slug($model->title) . '_' . $randomString . '.' . $image->extension;

what you should be doing is assign the instance of the uploaded file to the model field image and then call the $model->save() and use the custom filename to saveAs(), change your action code to the following

public function actionCreate()
{
    $model = new ItemForm();
    $model->scenario = ItemForm::SCENARIO_CREATE;

    if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
        Yii::$app->response->format = Response::FORMAT_JSON;
        return ActiveForm::validate($model);
    }

    if ($model->load(Yii::$app->request->post())) {

        $model->myFile = UploadedFile::getInstance($model, 'myFile');
        $randomString = Yii::$app->getSecurity()->generateRandomString(10);
        $model->image = Inflector::slug($model->title) . '_' . $randomString . '.' . $model->myFile->extension;

        $model->uploadItemImage();
        if ($model->save()) {
            return $this->redirect(['view', 'id' => $model->id]);
        }       
    } else {         
        return $this->render('create', [
            'model' => $model,             
        ]);
    }
}

and then create the following method inside your model

public function uploadItemImage(){
    $url = Image::URL . $this->image;
    if(!$this->myFile->saveAs($url)){
       $this->addError('myFile','Unable to save the uploaded file');
    }
}
Sign up to request clarification or add additional context in comments.

18 Comments

Hello Muhammad, thank you for your answer. Your code is great, but still I have validation error 'image field is required'. I thing that problem is in kartik-v/yii2-widget-fileinput extension. Its make hidden input with name 'image' and it is always empty.
there was still a mistake $this->saveAs() should be $this->image->saveAs(), and I have implemented it the same way I am also using this plugin, try logging here on the site by signing up with Facebook and try changing your profile picture potentialpads.idowstech.com, ideally when working with images I make a model separate for upload images or files. you are not doing it separately can you show your complete model code @Roboto6_1on
and i suspect that you have a field in your DB table with the name image?
here you have all my model form: paste.ofcode.org/tufSRbr2WPXKxX58bDhVPB | in DB I have 'image' => $this->string(),
you cannot map or apply validation to the database field instead you have to declare a custom field inside the model see my edit for details @Roboto6_1on
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.