Hoe te programmeren met Yii2 bestanden uploaden

Wat je gaat creëren

Als je vraagt: "Wat is Yii?" bekijk mijn eerdere tutorial: Introductie tot het Yii Framework, die de voordelen van Yii bekijkt en een overzicht bevat van wat er nieuw is in Yii 2.0, uitgebracht in oktober 2014.

In deze How to Program With Yii2-serie begeleid ik lezers in gebruik van het Yii2 Framework voor PHP. In deze zelfstudie leid ik je door de basisprincipes van het uploaden van bestanden en afbeeldingen in Yii2. 

Voor deze voorbeelden blijven we ons voorstellen dat we een raamwerk bouwen voor het plaatsen van eenvoudige statusupdates, bijvoorbeeld onze eigen mini-Twitter. De bovenstaande afbeelding toont het schrijven van een korte update tijdens het uploaden van een foto die ik van de Taj Mahal heb gemaakt.

Ter herinnering, ik neem wel deel aan de commentaarthreads hieronder. Ik ben vooral geïnteresseerd in verschillende benaderingen, aanvullende ideeën of onderwerpen voor toekomstige zelfstudies. Als u een vraag of een suggestie voor een onderwerp heeft, kunt u hieronder berichten plaatsen. Je kunt me ook rechtstreeks op Twitter @reifman bereiken.

Bestand Upload-plugins

Er zijn twee plug-ins voor het uploaden van bestanden voor Yii2 die het meest robuust lijken:

  1. De FileInput Widget van Kartik Visweswaran (hierboven afgebeeld)
  2. De 2Amigos BlueImp File Uploader (een wrapper voor de BlueImp JQuery File Uploader) 

Voor deze zelfstudie besloot ik door te gaan met de plug-in van Kartik. Ik vond het gemakkelijker te gebruiken en beter gedocumenteerd dan de 2Amigos plug-in. De BlueImp File Uploader heeft echter een aantal intrigerende functies voor gebruikerservaringen die u mogelijk wilt verkennen (hieronder weergegeven):

Werken met de FileInput-plug-in

Laten we beginnen met het installeren en gebruiken van de bestandsuploader en deze integreren in onze Twitter-achtige applet voor het maken van status. Nogmaals, we zullen de Yii2 Hello-toepassingsboom gebruiken die je kunt downloaden met de GitHub-knoplink naast of onder.

De plug-in installeren

Ten eerste kunnen we componist gebruiken om toe te voegen kartik-v / yii2-widget-fileinput naar onze applicatie:

$ composer vereist kartik-v / yii2-widget-fileinput "*" ./composer.json is bijgewerkt Bezig met laden van composer-repositories met pakketinformatie Bijwerken van afhankelijkheden (inclusief require-dev) - Bijwerken van kartik-v / yii2-widget-fileinput (dev -master 36f9f49 => v1.0.4) Controleren van 36f9f493c2d814529f2a195422a8af2e020fc80c Schrijfslotbestand Autoload bestanden genereren 

De statustabel uitbreiden

Vervolgens moeten we velden toevoegen voor het bestand dat we gaan uploaden naar onze statustabel. In dit voorbeeld laten we de gebruiker een afbeelding uploaden om mee te gaan met hun statusupdate.

De velden die we zullen toevoegen zijn voor de originele bestandsnaam van het bestand en een unieke bestandsnaam die op onze server wordt opgeslagen voor weergave:

  • image_src_filename
  • image_web_filename

Maak een nieuwe migratie voor het toevoegen van deze velden aan de tabel Status:

$ ./yii migrate / create extend_status_table_for_image Yii Migration Tool (gebaseerd op Yii v2.0.6) Maak nieuwe migratie '/Users/Jeff/Sites/hello/migrations/m160316_201654_extend_status_table_for_image.php'? (ja | nee) [nee]: ja Nieuwe migratie is succesvol gemaakt.

Dit is de aangepaste migratie om de twee velden als tekenreeksen toe te voegen:

db-> driverName === 'mysql') $ tableOptions = 'KARAKTER SET 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 ( '% de status', 'image_web_filename'); return false; 

Voer vervolgens de migratie uit:

$ ./yii migrate / up Yii Migration Tool (gebaseerd op Yii v2.0.6) Totaal 1 nieuwe migratie die moet worden toegepast: m160316_201654_extend_status_table_for_image Pas de bovenstaande migratie toe? (yes | no) [nee]: yes *** apply m160316_201654_extend_status_table_for_image> voeg kolom image_src_filename string NOT NULL toe aan tabel % status ... done (time: 0.044s)> voeg kolom image_web_filename string NOT NULL toe aan tabel % status ... klaar (tijd: 0.011s) *** toegepast m160316_201654_extend_status_table_for_image (tijd: 0.071s) Migratie succesvol uitgevoerd.

Omdat Yii2 is gebouwd met een MVC-architectuur (Model View Controller), zijn er drie andere codeergebieden die we moeten implementeren voor de uploader voor bestanden:

  1. Het statusmodel
  2. De statusweergave en het formulier
  3. De statuscontroller

Verbetering van de modelfunctionaliteit

Nu zullen we de wijzigingen aanbrengen /models/Status.php het dossier. In de eerste plaats moeten we kenmerken en validatieregels opgeven voor de nieuwe afbeeldingsvelden, evenals de tijdelijke image $ variabele die de widget gebruikt om het bestand te uploaden.

Hieronder voegen we opmerkingen toe voor de twee nieuwe $ image_xxx_filename variabelen en maak een openbare tijdelijke variabele genaamd image $:

/ ** * Dit is de modellens voor de status van de tabel. * * @property integer $ id * @property string $ message * @property integer $ permissies * @property string $ image_src_filename * @property string $ image_web_filename * @property integer $ created_at * @property integer $ updated_at * @property integer $ created_by * * @property Gebruiker $ createdBy * / class Status extends \ yii \ db \ ActiveRecord const PERMISSIONS_PRIVATE = 10; const PERMISSIONS_PUBLIC = 20; openbare $ afbeelding;

Vervolgens voegen we validatieregels toe voor onze afbeelding, zoals bestandstype en maximale grootte:

public function rules () return [['message'], 'required'], [['message'], 'string'], [['permissions', 'created_at', 'updated_at', 'created_by'] , 'integer'], [['afbeelding'], 'veilig'], [['afbeelding'], 'bestand', 'extensies' => 'jpg, gif, png'], [['afbeelding'], 'bestand', 'maxSize' => '100000'], [['image_src_filename', 'image_web_filename'], 'string', 'max' => 255],]; 

En nieuwe attribuutlabels voor weergaven:

 public function attributeLabels () return ['id' => Yii :: t ('app', 'ID'), 'message' => Yii :: t ('app', 'Message'), 'permissions' = > Yii :: t ('app', 'Permissions'), 'image_src_filename' => Yii :: t ('app', 'Filename'), 'image_web_filename' => Yii :: t ('app', 'Pathname '),' created_by '=> Yii :: t (' app ',' Created By '),' created_at '=> Yii :: t (' app ',' Created At '),' updated_at '=> Yii: : t ('app', 'Bijgewerkt bij'),]; 

Nu kunnen we verder gaan met de Wijzigingen bekijken binnen het ActiveModel-formulier.

Onze weergave- en formulierfunctionaliteit toevoegen

Afbeelding uploaden integreren naar het statusaanmaakformulier

Om de formulierintegratie van het uploaden van afbeeldingen naar Status-updates in te schakelen (hierboven weergegeven), moeten we wijzigingen aanbrengen in de /views/status/_form.php het dossier. 

Eerst nemen we de kartik \ file \ FileInput widget in de buurt van de top en werk het formulier bij om multipart te worden, wat het plaatsen van bestanden ondersteunt:

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

Vervolgens voegen we tussen de velden Machtigingen en Verzenden knoppen de FileInput-widget toe:

field ($ model, 'permissions') -> dropDownList ($ model-> getPermissions (), ['prompt' => Yii :: t ('app', '- Choose Your Permissions -')])?> 
field ($ model, 'image') -> widget (FileInput :: classname (), ['options' => ['accept' => 'image / *'], 'pluginOptions' => ['allowedFileExtensions' => ['jpg', 'gif', 'png'], 'showUpload' => false,],]); ?>
isNewRecord? Yii :: t ('app', 'Maken'): Yii :: t ('app', 'Update'), ['class' => $ model-> isNewRecord? 'btn btn-success': 'btn btn-primary'])?>

In de pluginOptions regel beperken we bestandstypen tot veelgebruikte afbeeldingsformaten zoals jpg.

Wanneer het is voltooid, ziet het er ongeveer zo uit en wacht het op de gebruiker om een ​​afbeelding toe te voegen:

De afbeelding weergeven

Ik ga ook code toevoegen om de geüploade afbeelding later weer te geven (nadat we de controller-ondersteuning hebben voltooid). 

Eerst zal ik het toevoegen aan de pagina Statusweergave (/views/status/view.php), wat erg basic is. Ik zal de afbeelding echter onder de itemdetails weergeven:

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

We voegen ook een kleine miniatuurweergave toe aan onze statusindexpagina (/views/status/index.php). Ik heb een aangepast kolomeigenschap toegevoegd aan de GridView-widget van Yii2:

 $ dataProvider, 'filterModel' => $ searchModel, 'columns' => [['class' => 'yii \ grid \ SerialColumn'], 'id', 'message: ntext', 'permissions', 'created_at', ['attribute' => 'Afbeelding', 'formaat' => 'onbewerkt', 'waarde' => functie ($ model) if ($ model-> image_web_filename! = ") retour ' '; anders return' no image ';,], [' class '=>' yii \ grid \ ActionColumn ',' template '=>' view update delete ',' buttons '=> [' view '=> functie ($ url, $ model) retourneer Html :: a ('',' status /'.$ model-> slug, ['title' => Yii :: t ('yii', 'View'),]); ],],],]); ?>

Uiteindelijk ziet het er als volgt uit:

De controllerondersteuning bouwen

Om al het bovenstaande mogelijk te maken, moeten we de controller-integratie voltooien. 

Bovenop /controllers/StatusController.php, we moeten opnemen Yii \ web \ UploadedFile:

Dan moeten we het updaten actionCreate functie:

public function actionCreate () $ model = nieuwe status (); if ($ model-> load (Yii :: $ app-> request-> post ())) $ image = UploadedFile :: getInstance ($ model, 'image'); if (! is_null ($ afbeelding)) $ model-> image_src_filename = $ image-> name; $ ext = end ((explode (".", $ image-> name))); // genereer een unieke bestandsnaam om dubbele bestandsnamen te voorkomen $ model-> image_web_filename = Yii :: $ app-> security-> generateRandomString (). ". $ ext"; // het pad om het bestand op te slaan, u kunt een uploadpad // instellen in Yii :: $ app-> params (zoals gebruikt in het onderstaande voorbeeld) Yii :: $ app-> params ['uploadPath'] = Yii :: $ app -> basePath. '/ Web / uploads / status van /'; $ path = Yii :: $ app-> params ['uploadPath']. $ Model-> image_web_filename; $ Beeld-> SaveAs ($ path);  if ($ model-> save ()) return $ this-> redirect (['view', 'id' => $ model-> id]);  else var_dump ($ model-> getErrors ()); dood gaan();  return $ this-> render ('create', ['model' => $ model,]); 

In wezen voert dit de volgende bewerkingen uit:

  1. We vangen de originele bestandsnaam op uit de formulierinformatie van het geüploade bestand (image_src_filename).
  2. We genereren een unieke bestandsnaam voor onze server (image_web_filename).
  3. We slaan het bestand op in onze upload-map (/ Web / uploads / staat /).
  4. We slaan het model op.
  5. We gaan door naar de pagina met verbeterde weergave.

Je kunt de eindresultaten zien met de bovenstaande afbeelding, inclusief een afbeelding van de Taj Mahal.

Kartik's File Input Widget biedt ook meer geavanceerde configuraties die hij redelijk goed documenteert, zoals Drag and Drop:

Bekijk hier meer over op de volgende pagina's:

  • FileInput Widget-demo
  • Upload het bestand in Yii 2 met behulp van de FileInput-widget
  • Geavanceerd uploaden met de widget Yii2 FileInput 

Wat is het volgende?

Ik hoop dat dit je helpt met de basisprincipes van het uploaden van bestanden in je Yii2-applicatie. Als je een andere soortgelijke doorloop van dit soort functionaliteit wilt zien, bekijk dan Start je startup met PHP: Gebruikersinstellingen, Profielafbeeldingen en Contactgegevens. Die tutorial biedt een iets andere integratie dan deze tutorial, met behulp van tabbladen, het bijwerken van gebruikersprofielen en het schalen van de afbeeldingen.

Kijk uit naar komende tutorials in mijn How to Program with Yii2-serie terwijl ik doorga met duiken in verschillende aspecten van het framework. Je kunt ook mijn Building Your Startup With PHP-serie bekijken, die de geavanceerde template van Yii2 gebruikt terwijl ik een real-world applicatie bouw.

Als je wilt weten wanneer de volgende Yii2-handleiding aankomt, volg me dan @reifman op Twitter of bekijk mijn instructeurspagina. Op mijn instructeurspagina staan ​​alle artikelen uit deze serie zodra ze zijn gepubliceerd. 

Gerelateerde Links

Hier zijn een aantal links die ik heb gebruikt om onderzoek te doen en deze tutorial te schrijven:

  • Yii2 Developer Exchange, mijn Yii2-bronsite
  • FileInput Widget Demo van - Kartik
  • Upload het bestand in Yii 2 met behulp van de FileInput-widget - Kartik
  • Code voor kartik-v / yii2-widget-fileinput (GitHub)
  • BlueImp JQuery Upload-demo uploaden
  • Code voor 2 amigos/yii2-file-upload-widget: BlueImp File Upload Widget (Github)
  • Bestanden uploaden - De definitieve gids voor Yii 2.0