4

I would like to upload multiple files at once. I have

a model:

class KakiKingModel extends ActiveRecord {

    public $uploadedFiles;

    public function rules() {
        return [
            [['uploadedFiles'], 'file', 'extensions' => 'txt', 'checkExtensionByMimeType' => false, 'skipOnEmpty' => true, 'maxFiles' => 2]];
    }
    ...

controller:

use yii\web\UploadedFile;
...
public function actionUpload() {
    $model = new KakiKingModel;
    $t = new KakiKingModel;

    if (Yii::$app->request->isPost) {
        $files = UploadedFile::getInstances($model, 'uploadedFiles');

        $t = [];
        $i = 0;
        foreach ($files as $i => $file) {
            $t[$i] = new KakiKingModel;
            $t[$i]->contentUploadedFile = file($file->tempName);
            $t[$i]->assign(); // assign file content to model attributes
            $i++;
        }

        if (Model::validateMultiple($t)) {
            foreach ($t as $item) {
                $item->save(false);
            }
            return $this->redirect(['index']);
        } else {
            return $this->render('upload', [
                        'model' => $model,
                        't' => $t,
            ]);
        }
    }

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

view:

$form = ActiveForm::begin([
    ....
    'options' => ['enctype' => 'multipart/form-data'],
    ...
        <?= $form->field($model, 'uploadedFiles[]')->fileInput(['multiple' => true]) ?>

and the problem is, it accepts any other type of files also! Why is that? What am I doing wrong? Thanks! UPDATE: I have changed my content a bit, so that you can better understand why I find it disturbing that it doesn't work. It should work IMHO. Can you please help me? Thank you!

user2511599
  • 796
  • 1
  • 13
  • 38

2 Answers2

4

Yii2 validation rules are applied for non-database model attributes too.

I think there are two common reasons for this problem:

1) Make sure you add correct enctype for sending files to server:

use yii\widgets\ActiveForm;

...

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

2) yii\validators\FileValidator (aliased with file) works only with yii\web\UploadedFile class instances (it's abstraction of PHP native superglobal $_FILES array), make sure you assign correct value to attribute before it's validated.

For single file use \yii\web\UploadedFile::getInstance():

use yii\web\UploadedFile;

...

$this->file = UploadedFile::getInstance($this, 'file');

For multiple files use \yii\web\UploadedFile::getInstance():

use yii\web\UploadedFile;

...

$this->files = UploadedFile::getInstances($this, 'files');

This can be done right before calling $model->save() or $model->validate() or inside of beforeValidate() event handler:

/**
 * @inheritdoc
 */
public function beforeValidate()
{
    $this->files = UploadedFile::getInstances($this, 'files');

    return parent::beforeValidate();
}
arogachev
  • 33,150
  • 7
  • 114
  • 117
  • okay, I hope I understand it. So the problem is, that somehow this assignment happens **after** validation by me? But at the moment, this command is tied to a `if (Yii::$app->request->isPost) {...` statement. Maybe a lame question, but how do I mix it with this `beforeValidate()` thing then...? – user2511599 Feb 04 '16 at 20:00
1

Try this way in your 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 $uploadedFiles;

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

IN view :

<?php
use yii\widgets\ActiveForm;

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

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

<button>Submit</button>

<?php ActiveForm::end(); ?>
Amitesh Kumar
  • 3,051
  • 1
  • 26
  • 42