Question

i have an ActiveForm, and i want to add a field where the user can upload their photos. the problem is that i don't have an attribute for the image in the users table and every input field in 'yii' expects a model and an attribute as follows.

<?= $form->field($model, 'attribute')->input($platforms) ?>

i don't want to assign the image to any record nor i want to insert in in the database, i want it to be uploaded to a specific folder.

i have also checked the library kartik wrote, but also requires an attribute field.

Was it helpful?

Solution

Follow the official documentation

https://github.com/yiisoft/yii2/blob/master/docs/guide/input-file-upload.md

Form Model

namespace app\models;

use yii\base\Model;
use yii\web\UploadedFile;

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

/**
 * @return array the validation rules.
 */
public function rules()
{
    return [
        [['file'], 'file'],
    ];
}
}
?>

Form View

<?php
use yii\widgets\ActiveForm;

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

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

<button>Submit</button>

<?php ActiveForm::end(); ?>

Controller

Now create the controller that connects form and model together:

<?php
namespace app\controllers;

use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;

class SiteController extends Controller
{
public function actionUpload()
{
    $model = new UploadForm();

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

        if ($model->validate()) {                
            $model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);
        }
    }

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

Instead of model->load(...) we are using UploadedFile::getInstance(...). [[\yii\web\UploadedFile|UploadedFile]] does not run the model validation. It only provides information about the uploaded file. Therefore, you need to run validation manually via $model->validate(). This triggers the [[yii\validators\FileValidator|FileValidator]] that expects a file:

 $file instanceof UploadedFile || $file->error == UPLOAD_ERR_NO_FILE //in code framework

If validation is successful, then we're saving the file:

 $model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);

If you're using "basic" application template then folder uploads should be created under web.

That's it. Load the page and try uploading. Uplaods should end up in basic/web/uploads.

OTHER TIPS

in your view

use kartik\widgets\ActiveForm;
use kartik\widgets\FileInput;

$form = ActiveForm::begin(['options' => ['enctype'=>'multipart/form-data']]); //important
echo FileInput::widget([
                    'name' => 'filename',
                    'showUpload' => false,
                    'buttonOptions' => ['label' => false],
                    'removeOptions' => ['label' => false],
                    'groupOptions' => ['class' => 'input-group-lg']
                ]);
echo Html::submitButton('Submit', ['class'=>'btn btn-primary']);
ActiveForm::end();

in your controller

$file = \yii\web\UploadedFile::getInstanceByName('filename');
$file->saveAs('/your/directory/'.$file->name);

Create a read only attribute for your model like public $imageand proceed like

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

I really like Yii2 Dropzone.

Installation:

composer require --prefer-dist perminder-klair/yii2-dropzone "dev-master"

Usage:

<?php 
    echo \kato\DropZone::widget([
       'options' => [
           'url'=> Url::to(['resource-manager/upload']),
           'paramName'=>'image',
           'maxFilesize' => '10',
       ],
       'clientEvents' => [
           'complete' => "function(file){console.log(file)}",
           'removedfile' => "function(file){alert(file.name + ' is removed')}"
       ],
   ]);

   ?>

Controller:

public function actionUpload(){

        $model = new ResourceManager();
        $uploadPath = Yii::getAlias('@root') .'/uploads/';

        if (isset($_FILES['image'])) {
            $file = \yii\web\UploadedFile::getInstanceByName('image');
          $original_name = $file->baseName;  
          $newFileName = \Yii::$app->security
                            ->generateRandomString().'.'.$file->extension;
           // you can write save code here before uploading.
            if ($file->saveAs($uploadPath . '/' . $newFileName)) {
                $model->image = $newFileName;
                $model->original_name = $original_name;
                if($model->save(false)){
                    echo \yii\helpers\Json::encode($file);
                }
                else{
                    echo \yii\helpers\Json::encode($model->getErrors());
                }

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

        return false;
    }

give this code after your uploaded code

  //save the path in DB..
                $model->file = 'uploads/'.$imageName.'.'.$model->file->extension;
                $model->save();

If you have more than one file while uploading you must use foreach for that. And you should actual name of file in a column in table and a encrypted value of that name has to be stored to avoid duplicated in the directory.. Something like this..

$userdocs->document_name = UploadedFile::getInstances($userdocs, 'document_name');

foreach ($userdocs->document_name as $key => $file) {
  $img_name = Yii::$app->security->generateRandomString();
  $file->saveAs('user/business_files/' . $img_name . '.' . $file->extension);
  $images = $img_name . '.' . $file->extension;
  $userdocs->actual_name = $file->name;
  $userdocs->user_id = $user->id;
  $userdocs->document_name = $images;
  $userdocs->save(false);
  $userdocs = new UserDocs();
}

Here a random string is generated and it will be assign with the name of the document, and it will be stored in the table. The UserDocs is the model name.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top