2015-03-27 9 views
5

Jest to sytuacja: Jestem nowy na Yii2 i chciał użyć jakiś widget do przesyłania plików w ciągu ActiveForm .. tak daleko Znalazłem ten Excelent One: \kartik\widget\FileInputyii2 - Kartik plik wejściowy - aktualizację

Z tego widget Mogę zarządzać przesyłaniem plików, a następnie, po wejściu w tryb edycji, pokazać poprzedni przesłany obraz z oportunite, aby go zastąpić.

Problem polega na tym, że po naciśnięciu przycisku "Aktualizuj" formularza bez modyfikacji obrazu yii mówi, że obraz "nie może być pusty", ponieważ ustawiłem "wymaganą" regułę w moim modelu.

Odpowiedz

5

Po okropnym południu i bardziej produktywnego nocy, z jaką się spotkałem rozwiązanie, które pracowały dla mnie ..

Głównym problemem było to, że plik wejściowy nie wysyłać jej wartość (nazwa pliku zapisanego w baza danych) podczas aktualizacji. Wysyła informacje o obrazie tylko wtedy, gdy przeglądanie i wybieranie odbywa się za pośrednictwem pliku wejściowego.

Moje obejście polegało na utworzeniu kolejnego "wirtualnego" pola do zarządzania przesyłaniem plików o nazwie "upload_image". Aby to osiągnąć, ja prosty dodał własność publiczną o tej nazwie do mojej klasy modelu public $upload_image;

ja również dodać walidację folowing metody przepisami dotyczącymi klasy modelu:

public function rules() 
{ 
    return [ 
     [['upload_image'], 'file', 'extensions' => 'png, jpg', 'skipOnEmpty' => true], 
     [['image'], 'required'], 
    ]; 
} 

Tutaj „upload_image” to mój wirtualny kolumna. Dodałem walidację "pliku" za pomocą "skipOnEmpty" = true, a "image" to pole w mojej bazie danych, które musi być wymagane w moim przypadku.

Wtedy, moim zdaniem mam skonfigurowany 'upload_image' widget jak następuje:

echo FileInput::widget([ 
     'model' => $model, 
     'attribute' => 'upload_image', 
     'pluginOptions' => [ 
      'initialPreview'=>[ 
       Html::img("/uploads/" . $model->image) 
      ], 
      'overwriteInitial'=>true 
     ] 
    ]); 

W opcji 'initialPreview' I asign moje imię obrazu, zapisany w '$ model-> Obraz' własności zwracanych z bazy danych.

Wreszcie mój kontroler wygląda następująco:

public function actionUpdate($id) 
{ 
    $model = $this->findModel($id); 
    $model->load(Yii::$app->request->post()); 

    if(Yii::$app->request->isPost){ 
     //Try to get file info 
     $upload_image = \yii\web\UploadedFile::getInstance($model, 'upload_image'); 

     //If received, then I get the file name and asign it to $model->image in order to store it in db 
     if(!empty($upload_image)){ 
      $image_name = $upload_image->name; 
      $model->image = $image_name; 
     } 

     //I proceed to validate model. Notice that will validate that 'image' is required and also 'image_upload' as file, but this last is optional 
     if ($model->validate() && $model->save()) { 

      //If all went OK, then I proceed to save the image in filesystem 
      if(!empty($upload_image)){ 
       $upload_image->saveAs('uploads/' . $image_name); 
      } 

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

Spróbuj docisku pola wejściowego pliku z zawartością tej dziedzinie. W ten sposób nie utracisz danych po przesłaniu formularza.

Przejrzałem kartik file-input widget (miły znaleźć, btw) i natknąłem się na taki sposób, aby to zrobić

// Display an initial preview of files with caption 
// (useful in UPDATE scenarios). Set overwrite `initialPreview` 
// to `false` to append uploaded images to the initial preview. 
echo FileInput::widget([ 
    'name' => 'attachment_49[]', 
    'options' => [ 
     'multiple' => true 
    ], 
    'pluginOptions' => [ 
     'initialPreview' => [ 
      Html::img("/images/moon.jpg", ['class'=>'file-preview-image', 'alt'=>'The Moon', 'title'=>'The Moon']), 
      Html::img("/images/earth.jpg", ['class'=>'file-preview-image', 'alt'=>'The Earth', 'title'=>'The Earth']), 
     ], 
     'initialCaption'=>"The Moon and the Earth", 
     'overwriteInitial'=>false 
    ] 
]); 

Można też na relaks required regułę w modelu dla tej dziedzinie, więc nie narzekać na walidację. Możesz poprosić użytkownika o subtelniejsze środki.

3

Zetknąłem się z innym rozwiązaniem, tworząc scenariusze. W twoim przypadku zmodyfikuję takie reguły:

public funtion rules() { 
    [['image'], 'file'], 
    [['image'], 'required', 'on'=> 'create'] 
} 

Tak więc pole fileupload będzie wymagane tylko w akcji tworzenia. W akcji aktualizacji mam ten kod:

public function actionUpdate($id) 
    { 
     $model = $this->findModel($id); 

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

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

      if (!empty($newCover)) { 
      $newCoverName = Yii::$app->security->generateRandomString(); 
      unlink($model->cover); 
      $model->cover = 'uploads/covers/' . $newCoverName . '.' . $newCover->extension; 
      $newCover->saveAs('uploads/covers/' . $newCoverName . '.' . $newCover->extension); 
      } 

      if ($model->validate() && $model->save()) { 
      return $this->redirect(['view', 'id' => $model->post_id]); 
      } else { 
      // error saving model 
      } 

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

    } 

w scenariuszu aktualizacji obraz złożony nie jest wymagane, ale kontroli kodu, jeśli nic nie zostało dodane i nie zmienia poprzednią wartość.

Mój plik forma:

<?= $form->field($model, 'image')->widget(FileInput::classname(), [ 
    'options' => ['accept'=>'image/*'], 
    'pluginOptions'=>[ 
     'allowedFileExtensions'=>['jpg', 'gif', 'png', 'bmp'], 
     'showUpload' => true, 
     'initialPreview' => [ 
      $model->cover ? Html::img($model->cover) : null, // checks the models to display the preview 
     ], 
     'overwriteInitial' => false, 
    ], 
]); ?> 

moim zdaniem jest trochę łatwiej niż polu wirtualnej. Mam nadzieję, że to pomoże!

-2

Od Krajee:

http://webtips.krajee.com/advanced-upload-using-yii2-fileinput-widget

Tworzenie, usuwanie, zmiana: bardzo łatwy, nie patrzeć dalej.

(1) Ustawiłem również "wymaganą" regułę w moim modelu.

(2) do pracy w -WampSerwer:

Yii::$app->params['uploadPath'] = Yii::$app->basePath . '/web/uploads/'; 

Yii::$app->params['uploadUrl'] = Yii::$app->urlManager->baseUrl . '/uploads/'; 
Powiązane problemy