Dmitry
Dmitry

Reputation: 261

How create file input at form, which upload file and write link in database

I'm trying to learn Yii2 by writing my own cms.

I want realize attachment photo for shop items. I don't know right way to do this, but i think it's should be so -

  1. On save, files which was selected in multiple file input are uploads to server.
  2. Get the url by each photo
  3. Write links in database cell by template

    <div class="itemImgs">
        <img class="0" src="{link}"> <!-- first -->
        <img class="1" src="{link}"> <!-- second -->
        <img class="..." src="{link}"> <!-- ... -->
    </div>
    

Please, help me understand, what i must write in model and\or controller, if its right way. Else, please tell me how should to do it.

Thanks.

UPD

Action in controller:

  public function actionCreate() {
    $model = new ShopItems();
    if ($model->load(Yii::$app->request->post()) && $model->save()) {
      return $this->redirect(['view', 'id' => $model->id]);
    } else {
      return $this->render('create', [
        'model' => $model,
        'category' => ShopCategories::find()->all()
      ]);
    }
  }

Model contain this functions:

  public function behaviors() {
    return [
      TimestampBehavior::className(),
    ];
  }

  /** @inheritdoc */
  public static function tableName() {return 'shop_items';}

  /** @inheritdoc */
  public function rules() {
    return [
      [['category_id', 'title', 'desc', 'price', ], 'required'],
      [['category_id', 'price', 'in_stock', 'discount',], 'integer'],
      [['desc', 'options',], 'string'],
      [['photos',], 'file', 'maxFiles' => 10],
      [['title'], 'string', 'max' => 100]
    ];
  }

  /** @inheritdoc */
  public function attributeLabels() {
    return [
      'id' => 'ID',
      'category_id' => 'Категория',
      'title' => 'Название',
      'desc' => 'Описание',
      'price' => 'Цена',
      'discount' => 'Скидка %',
      'in_stock' => 'На складе',
      'photos' => 'Фото',
      'options' => 'Опции',
      'created_at' => 'Дата добавления',
      'updated_at' => 'Последнее редактирование',
    ];
  }

And the view _form.php:

  <?php $form = ActiveForm::begin(); ?>

    <div class="col-lg-6">

      <?= $form->field($model, 'title')->textInput(['maxlength' => 100]) ?>

      <?= $form->field($model, 'desc')->textarea(['class' => 'ckeditor',]);  ?>

    </div>
    <div class="col-lg-6">

      <?= $form->field($model, 'category_id')->dropDownList(
        ArrayHelper::map($category, 'category_id', 'category_name')
      ) ?>

      <?= $form->field($model, 'price')->textInput() ?>

      <?= $form->field($model, 'discount')->textInput() ?>

      <?= $form->field($model, 'in_stock')->textInput() ?>

      <?= $form->field($model, 'photos[]')->fileInput(['multiple' => true]) ?>

      <?= $form->field($model, 'options')->textInput() ?>

    </div>

    <div class="clearfix"></div>

    <div class="col-xs-12">
      <div class="form-group">
        <?= Html::submitButton($model->isNewRecord ? 'Добавить' : 'Принять изменения', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
      </div>
    </div>

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

Upvotes: 1

Views: 2484

Answers (1)

vitalik_74
vitalik_74

Reputation: 4591

See documentation - http://www.yiiframework.com/doc-2.0/guide-input-file-upload.html#uploading-multiple-files

In controller:

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

Input model Photo:

if ($model->file && $model->validate()) {
                foreach ($model->file as $file) {
                    $path = 'uploads/' . $file->baseName . '.' . $file->extension;
                    $file->saveAs($path);
                    $photo = new Photo();
                    $photo->path = $path; 
                    $photo->save();
                }
            }

Photo table like that:

CREATE TABLE `photo` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `path` VARCHAR(255) NOT NULL ,
    `status` TINYINT(1) NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`)
)
ENGINE=InnoDB;

Get photos use:

$photos = Photo::find()->all();

In view:

<div class="itemImgs">
    <?php foreach ($photos as $k=>$photo) ?>
     <img class="<?= $k ?>" src="<?= $photo->path ?>"/><br/>
    <?php } ?>
</div>

EDIT Set in controller

 if ($model->load(Yii::$app->request->post()) && $model->validate()) {
     $files = UploadedFile::getInstances($model, 'file');
     $photosArr = [];
     foreach ($files as $file) {
        $path = 'uploads/' . $file->baseName . '.' . $file->extension;
        $file->saveAs($path);
        $photosArr[] = $path;
     }

     $model->photos = Json::encode($photosArr);// better put json in afterSave
     $model->save(false);// because validate() run before

      return $this->redirect(['view', 'id' => $model->id]);
    }

In field photos you get JSON with path for uploaded photos. In view:

$arr = Json::decode($model->photos); // better put in afterFind()
foreach ($arr as $path) {
  echo '<img src="'.$path.'">';
}

Upvotes: 2

Related Questions