file-uploadyii2yii2-model

is it possible to upload a file in a model that inherits from ActiveRecord in yii2?


I generated a model with Gii from a database table in yii2.this model inherits from ActiveRecord . then I created a form from this model.now I want to upload a file with this form. is it possible to upload file with same model (that inherits from ActiveRecord)?

if yes , how ? if no , what can I do?


Solution

  • Yes, it's possible, but using separate form is better practice. It's well described in official documentation in article Uploading files

    Create separate form:

    namespace app\models;
    
    use yii\base\Model;
    use yii\web\UploadedFile;
    
    class UploadForm extends Model
    {
        /**
         * @var UploadedFile
         */
        public $imageFile;
    
        public function rules()
        {
            return [
                [['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
            ];
        }
    
        public function upload()
        {
            if ($this->validate()) {
                $this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
                return true;
            } else {
                return false;
            }
        }
    }
    

    Render file input:

    <?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
    
        <?= $form->field($model, 'imageFile')->fileInput() ?>
    
        <button>Submit</button>
    
    <?php ActiveForm::end() ?>
    

    Customize controller to handle file uploads:

    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->imageFile = UploadedFile::getInstance($model, 'imageFile');
                if ($model->upload()) {
                    // file is uploaded successfully
                    return;
                }
            }
    
            return $this->render('upload', ['model' => $model]);
        }
    }
    

    Uploading multiple files is also covered in this article.

    Also see this related question.

    If you want to use it with ActiveRecord and save filepath as model attribute, you can add model creation and saving in upload() method of form. Another good example of working with forms is SignupForm from Advanced Template:

    <?php
    
    namespace frontend\models;
    use yii\base\Model;
    use common\models\User;
    
    /**
     * Signup form
     */
    class SignupForm extends Model
    {
        public $username;
        public $email;
        public $password;
    
    
        /**
         * @inheritdoc
         */
        public function rules()
        {
            return [
                ['username', 'trim'],
                ['username', 'required'],
                ['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
                ['username', 'string', 'min' => 2, 'max' => 255],
                ['email', 'trim'],
                ['email', 'required'],
                ['email', 'email'],
                ['email', 'string', 'max' => 255],
                ['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],
                ['password', 'required'],
                ['password', 'string', 'min' => 6],
            ];
        }
    
        /**
         * Signs user up.
         *
         * @return User|null the saved model or null if saving fails
         */
        public function signup()
        {
            if (!$this->validate()) {
                return null;
            }
    
            $user = new User();
            $user->username = $this->username;
            $user->email = $this->email;
            $user->setPassword($this->password);
            $user->generateAuthKey();
    
            return $user->save() ? $user : null;
        }
    }
    

    As you can see, validation and creation of model is isolated into separate form, this is better practice rather than processing it directly in model (especially file uploads). But for simple purposes using just model can be acceptable too.