Come programmare con Yii2 caricamento di file

Cosa starai creando

Se stai chiedendo "Cos'è Yii?" guarda il mio tutorial precedente: Introduzione al framework Yii, che rivede i vantaggi di Yii e include una panoramica delle novità in Yii 2.0, rilasciata nell'ottobre 2014.

In questo How to Program con la serie Yii2, guido i lettori nell'uso di Yii2 Framework per PHP. In questo tutorial, ti guiderò attraverso le basi del caricamento di file e immagini in Yii2. 

Per questi esempi, continueremo a immaginare che stiamo costruendo un framework per la pubblicazione di semplici aggiornamenti di stato, ad es. il nostro mini-Twitter. L'immagine sopra mostra la scrittura di un breve aggiornamento durante il caricamento di una foto che ho preso del Taj Mahal.

Solo un promemoria, parteciperò alle discussioni dei commenti qui sotto. Sono particolarmente interessato se hai approcci diversi, idee aggiuntive o vuoi suggerire argomenti per futuri tutorial. Se hai una domanda o un suggerimento sull'argomento, per favore pubblica qui sotto. Puoi anche raggiungermi su Twitter direttamente @reifman.

File Upload Plugin

Ci sono due plugin per caricare file per Yii2 che sembrano i più robusti:

  1. Il Widget FileInput di Kartik Visweswaran (mostrato sopra)
  2. 2Amigos BlueImp File Uploader (un wrapper per il file Uploader JQuery BlueImp) 

Per questo tutorial, ho deciso di continuare con il plugin di Kartik. L'ho trovato più facile da usare e meglio documentato rispetto al plugin 2Amigos. Tuttavia, il BlueImp File Uploader ha alcune caratteristiche intriganti di esperienza utente che potresti voler esplorare (vedi sotto):

Funzionando con il plugin FileInput

Iniziamo a installare e utilizzare l'uploader di file e integrarlo nella nostra applet di creazione dello stato simile a Twitter. Di nuovo, utilizzeremo l'albero delle applicazioni di Yii2 Hello che puoi scaricare con il link del pulsante GitHub accanto o sotto.

Installare il plugin

Innanzitutto, possiamo usare il compositore per aggiungere Kartik-v / yii2-widget di-fileinput alla nostra applicazione:

$ compositore richiede kartik-v / yii2-widget-fileinput "*" ./composer.json è stato aggiornato Caricamento dei repository di compositore con informazioni sul pacchetto Aggiornamento delle dipendenze (incluso require-dev) - Aggiornamento di kartik-v / yii2-widget-fileinput (dev -master 36f9f49 => v1.0.4) Verifica 36f9f493c2d814529f2a195422a8af2e020fc80c Scrittura del file di blocco Generazione dei file di caricamento automatico 

Espansione della tabella di stato

Successivamente, dobbiamo aggiungere campi per il file che stiamo per caricare nella nostra tabella di stato. In questo esempio, consentiremo all'utente di caricare un'immagine per accompagnare il suo aggiornamento di stato.

I campi che aggiungeremo riguardano il nome file originale dei file caricati e un nome file univoco che verrà memorizzato sul nostro server per la visualizzazione:

  • image_src_filename
  • image_web_filename

Crea una nuova migrazione per aggiungere questi campi alla tabella Stato:

$ ./yii migrate / create extend_status_table_for_image Strumento di migrazione Yii (basato su Yii v2.0.6) Crea nuova migrazione '/Users/Jeff/Sites/hello/migrations/m160316_201654_extend_status_table_for_image.php'? (sì | no) [no]: sì Nuova migrazione creata con successo.

Ecco la migrazione personalizzata per aggiungere i due campi come stringhe:

db-> driverName === 'mysql') $ tableOptions = 'SET CARATTERE utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB';  $ this-> addColumn ('% status', 'image_src_filename', Schema :: TYPE_STRING. 'NOT NULL'); $ this-> addColumn ('% status', 'image_web_filename', Schema :: TYPE_STRING. 'NOT NULL');  public function down () $ this-> dropColumn ('% status', 'image_src_filename'); $ This-> dropColumn ( 'status%', 'image_web_filename'); restituisce falso; 

Quindi, esegui la migrazione:

$ ./yii migrate / up Yii Migration Tool (basato su Yii v2.0.6) Totale 1 nuova migrazione da applicare: m160316_201654_extend_status_table_for_image Applicare la migrazione sopra? (sì | no) [no]: sì *** applicando m160316_201654_extend_status_table_for_image> aggiungi colonna image_src_filename stringa NOT NULL alla tabella % status ... done (time: 0.044s)> aggiungi colonna image_web_filename stringa NOT NULL alla tabella % status ... done (time: 0.011s) *** applicato m160316_201654_extend_status_table_for_image (time: 0.071s) Migrato con successo.

Poiché Yii2 è costruito con un'architettura MVC (Model View Controller), ci sono altre tre aree di codifica che dobbiamo implementare per l'uploader di file:

  1. Il modello di stato
  2. La visualizzazione dello stato e il modulo
  3. Il controller di stato

Migliorare la funzionalità del modello

Ora apporteremo modifiche al /models/Status.php file. In primo luogo, dobbiamo fornire attributi e regole di convalida per i nuovi campi immagine e anche per quelli temporanei $ image variabile che il widget utilizzerà per caricare il file.

Sotto, aggiungiamo commenti per i due nuovi $ image_xxx_filename variabili e creare una variabile temporanea pubblica chiamata $ image:

/ ** * Questa è la classe del modello per lo "stato" della tabella. * * @property intero $ id * @property stringa $ messaggio * @property intero $ permessi * @property stringa $ image_src_filename * @property stringa $ image_web_filename * @property intero $ created_at * @property intero $ updated_at * @property intero $ created_by * * @property User $ createdBy * / class Status extends \ yii \ db \ ActiveRecord const PERMISSIONS_PRIVATE = 10; const PERMISSIONS_PUBLIC = 20; immagine $ pubblica;

Successivamente, aggiungeremo regole di convalida per la nostra immagine come il tipo di file e la dimensione massima:

public function rules () return [['message'], 'required'], [['message'], 'string'], [['permessi', 'created_at', 'updated_at', 'created_by'] , "intero"], [['immagine'], 'sicuro'], [['immagine'], 'file', 'estensioni' => 'jpg, gif, png'], [['immagine'], 'file', 'maxSize' => '100000'], [['image_src_filename', 'image_web_filename'], 'string', 'max' => 255],]; 

E nuove etichette di attributi per le viste:

 public function attributeLabels () return ['id' => Yii :: t ('app', 'ID'), 'message' => Yii :: t ('app', 'Message'), 'permessi' = > Yii :: t ('app', 'Permessi'), 'image_src_filename' => Yii :: t ('app', 'Filename'), 'image_web_filename' => Yii :: t ('app', 'Pathname '),' created_by '=> Yii :: t (' app ',' Creato da '),' created_at '=> Yii :: t (' app ',' Creato a '),' updated_at '=> Yii: : t ('app', 'Aggiornato a'),]; 

Ora possiamo passare alle modifiche Visualizza all'interno del modulo ActiveModel.

Aggiungere la nostra vista e la funzionalità della forma

Integrazione del caricamento dell'immagine nel modulo di creazione dello stato

Per abilitare l'integrazione del modulo di caricamento delle immagini agli aggiornamenti di stato (mostrati sopra), è necessario apportare modifiche al file /views/status/_form.php file. 

Primo, includiamo il Kartik \ file \ FileInput widget in alto e aggiornare il modulo per diventare multipart, che supporta la pubblicazione di file:

 
[ 'Enctype' => 'multipart / form-data']]); // importante?>

Quindi, tra il campo Autorizzazioni e i pulsanti Invia, aggiungiamo il widget FileInput:

campo ($ model, 'permessi') -> dropDownList ($ model-> getPermissions (), ['prompt' => Yii :: t ('app', '- Scegli i permessi -')]? 
field ($ model, 'image') -> widget (FileInput :: classname (), ['options' => ['accept' => 'image / *'], 'pluginOptions' => ['allowedFileExtensions' => ['jpg', 'gif', 'png'], 'showUpload' => false,],]); ?>
isNewRecord? Yii :: t ('app', 'Crea'): Yii :: t ('app', 'Aggiorna'), ['classe' => $ modello-> isNewRecord? 'btn btn-success': 'btn btn-primary'])?>

Nel pluginOptions linea, limitiamo i tipi di file a formati di immagine comuni come jpg.

Al termine, sarà simile a questa, in attesa che l'utente aggiunga un'immagine:

Visualizzazione dell'immagine

Aggiungerò anche del codice per visualizzare l'immagine caricata per dopo (dopo aver terminato il supporto del controller). 

Innanzitutto, lo aggiungerò alla pagina della vista Stato (/views/status/view.php), che è molto semplice. Tuttavia, visualizzerò l'immagine sotto i dettagli dell'articolo:

 $ model, 'attributes' => ['id', 'createdBy.email', 'message: ntext', 'permissions', 'image_web_filename', 'image_src_filename', 'created_at', 'updated_at',],])? > image_web_filename! = ") echo '

'; ?>

Sembrerà qualcosa del genere:

Aggiungiamo anche una piccola anteprima alla nostra pagina dell'indice di stato (/views/status/index.php). Ho aggiunto un attributo di colonna personalizzato al widget GridView di Yii2:

 $ dataProvider, 'filterModel' => $ searchModel, 'columns' => [['class' => 'yii \ grid \ SerialColumn'], 'id', 'message: ntext', 'permessi', 'created_at', ['attribute' => 'Image', 'format' => 'raw', 'value' => function ($ model) if ($ model-> image_web_filename! = ") return ' '; else return' no image ';,], [' class '=>' yii \ grid \ ActionColumn ',' template '=>' view update delete ',' buttons '=> [' view '=> function ($ url, $ model) return Html :: a ('',' status /'.$ model-> slug, ['title' => Yii :: t ('yii', 'View'),]); ],],],]); ?>

In definitiva, assomiglierà a questo:

Costruire il supporto per i controller

Per rendere possibile tutto quanto sopra, dobbiamo completare l'integrazione del controller. 

In cima a /controllers/StatusController.php, dobbiamo includere Yii \ web \ UploadedFile:

Quindi dobbiamo aggiornare il ActionCreate funzione:

funzione pubblica actionCreate () $ model = new Status (); if ($ model-> load (Yii :: $ app-> request-> post ())) $ image = UploadedFile :: getInstance ($ model, 'image'); if (! is_null ($ image)) $ model-> image_src_filename = $ image-> name; $ ext = end ((explode (".", $ image-> name))); // genera un nome file univoco per impedire nomi file duplicati $ model-> image_web_filename = Yii :: $ app-> security-> generateRandomString (). ". $ ext"; // il percorso per salvare il file, puoi impostare un uploadPath // in Yii :: $ app-> params (come usato nell'esempio sotto) Yii :: $ app-> params ['uploadPath'] = Yii :: $ app -> basePath. '/ Web / uploads / stato /'; $ percorso = Yii :: $ app-> parametri ['uploadPath']. $ Modello-> image_web_filename; $ Immagine-> saveAs ($ path);  if ($ model-> save ()) return $ this-> redirect (['view', 'id' => $ model-> id]);  else var_dump ($ model-> getErrors ()); morire();  restituisce $ this-> render ('create', ['model' => $ model,]); 

In sostanza, questo esegue le seguenti operazioni:

  1. Acquisiamo il nome file originale dalle informazioni del modulo del file caricato (image_src_filename).
  2. Generiamo un nome file univoco per il nostro server (image_web_filename).
  3. Salviamo il file nella nostra directory di upload (/ Web / uploads / Stato /).
  4. Salviamo il modello.
  5. Reindirizziamo alla pagina di visualizzazione avanzata.

Puoi vedere i risultati finali con l'immagine sopra, che include un'immagine del Taj Mahal.

Kartik's File Input Widget offre anche configurazioni più avanzate che documenta abbastanza bene, come Drag and Drop:

Controlla più di questi nelle seguenti pagine:

  • Demo del widget FileInput
  • Carica il file in Yii 2 usando il widget FileInput
  • Caricamento avanzato utilizzando il widget FileInput Yii2 

Qual'è il prossimo?

Spero che questo ti aiuti con le basi del caricamento dei file nella tua applicazione Yii2. Se desideri vedere un altro esempio di questo tipo di funzionalità, consulta Creazione di avvio con PHP: Impostazioni utente, Immagini profilo e Dettagli contatto. Quel tutorial offre un'integrazione leggermente diversa rispetto a questo tutorial, utilizzando le schede, aggiornando i profili utente e ridimensionando le immagini.

Guarda le prossime esercitazioni nella mia serie Come programmare con Yii2 mentre continuo a immergermi nei diversi aspetti del framework. Potresti anche voler controllare la mia creazione della tua startup con la serie PHP, che usa il modello avanzato di Yii2 mentre costruisco un'applicazione reale.

Se vuoi sapere quando arriverà il prossimo tutorial di Yii2, seguimi @reifman su Twitter o controlla la mia pagina di istruttore. La mia pagina di istruttore includerà tutti gli articoli di questa serie non appena saranno pubblicati. 

Link correlati

Qui ci sono una varietà di link che ho usato per cercare e scrivere questo tutorial:

  • Yii2 Developer Exchange, il mio sito di risorse Yii2
  • Demo di Widget FileInput di - Kartik
  • Carica il file in Yii 2 usando il widget FileInput - Kartik
  • Codice per kartik-v / yii2-widget-fileinput (GitHub)
  • BlueImp JQuery File Upload Demo
  • Codice per 2 amigos/yii2-file-upload-widget: BlueImp File Upload Widget (Github)
  • Uploading Files - The Definitive Guide to Yii 2.0