2015-03-27 17 views
5

Questa è la situazione: io sono nuovo su Yii2 e volevo utilizzare alcuni widget di file di uploader entro ActiveForm .. finora ho trovato questo eccellente uno: \kartik\widget\FileInputyii2 - file di Kartik ingresso - aggiornamento

Con questa widget Posso gestire il caricamento di file e quindi, quando entri in modalità di modifica, mostra l'immagine caricata in precedenza con l'oportunite per sostituirla.

Il problema è che se premo il pulsante "Aggiorna" del modulo senza modificare l'immagine, yii dice che l'immagine "non può essere vuota" perché ho impostato la regola "richiesta" nel mio modello.

risposta

5

Dopo un pomeriggio e una notte terribile più produttivo, ho incontrato una soluzione che ha funzionato per me ..

Il problema principale era che il file di input non inviare il suo valore (nome del file memorizzato in database) durante l'aggiornamento. Invia solo le informazioni sull'immagine se visualizzate e selezionate tramite l'input del file.

Quindi, la mia soluzione era creare un altro campo "virtuale" per la gestione del caricamento di file, denominato "upload_image". Per raggiungere questo obiettivo ho semplice aggiunta di una proprietà pubblica con questo nome per la mia classe del modello: public $upload_image;

Ho anche aggiungere la convalida seguente per il metodo norme sulla classe del modello:

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

Qui, 'upload_image' è il mio virtual colonna. Ho aggiunto la convalida 'file' con 'skipOnEmpty' = true, e 'image' è il campo sul mio database, che deve essere richiesto nel mio caso.

Poi, a mio avviso ho configurato 'upload_image' widget di come segue:

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

In opzione 'initialPreview' Io Asign il mio nome dell'immagine, memorizzato in 'immagine $ modello->' beni restituiti dal database.

Infine, il mio controller si presenta come segue:

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

Prova precarico il campo di immissione di file con il contenuto di quel campo. In questo modo, non perderai i dati dopo aver inviato il modulo.

ho guardato attraverso kartik file-input widget (bella scoperta, btw) e mi sono imbattuto in un modo per fare questo

// 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 
    ] 
]); 

Si consiglia inoltre di rilassare la required regola nel modello per il campo, in modo da non lamentarsi sulla convalida È possibile scegliere di richiedere all'utente attraverso mezzi più sottili.

3

Ho incontrato un'altra soluzione creando scenari. Nel tuo caso avrei modificare le regole in questo modo:

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

Così il campo FileUpload saranno richiesti solo nel creare azioni. In azione di aggiornamento ho questo codice:

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, 
      ]); 
     } 

    } 

Nello scenario di aggiornamento dell'immagine depositato non è necessario, ma il codice verifica se nulla è stato caricato e non cambia il valore precedente.

La mia forma file:

<?= $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, 
    ], 
]); ?> 

credo sia un po 'più facile che un campo virtuale. Spero che sia d'aiuto!

-2

Da Krajee:

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

creare, cancellare, aggiornare: davvero facile, non cercate oltre.

(1) Ho impostato la regola "richiesta" anche nel mio modello.

(2) Per lavorare su Wampserver:

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

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