Laravel-Tutorial für Anfänger

Was ist Laravel?

Laravel ist ein Open-Source-Web-MVC-Framework für PHP. Laravel ist ein robustes Framework, das die einfache Entwicklung von PHP-Webanwendungen mit Funktionen wie einem modularen Paketsystem mit einem dedizierten Abhängigkeitsmanager, Zugriff auf relationale Datenbanken und anderen Dienstprogrammen für die Anwendungsbereitstellung und -wartung ermöglicht.

Laravel wurde von Taylor Otwell erstellt. Seit seiner ersten Veröffentlichung im Juni 2011 (Version 1) erfreut es sich im PHP-Framework-Bereich der Webentwicklungsbranche immer größerer Beliebtheit. Ein großer Teil dieser Beliebtheit ist auf die vielen entwicklerorientierten Funktionen zurückzuführen, die im Lieferumfang enthalten sind.

Warum Laravel?

Meistens um 2000 PHP-Codes war prozedural und konnte in Form von „Skripten“ gefunden werden, die ein Durcheinander von Spaghetti-Code enthielten. Selbst die einfachsten Seiten hatten keine Trennung von Bedenken, und daher konnte es für eine Anwendung ziemlich leicht passieren, dass sie sich schnell zu einem Wartungsalbtraum entwickelte. Die Welt brauchte etwas Besseres … Hier kommen PHP Version 5 und eine Vielzahl von PHP-Frameworks zum Einsatz, die versuchen, dringend benötigte Lösungen und bessere Lösungen für verschiedene Webanwendungsprobleme zu schaffen.

Seitdem wurden viele Frameworks veröffentlicht, die den Weg für die heute existierenden und eingesetzten beliebten Frameworks ebneten. Heute sind die Top 3 (unserer Meinung nach) Zend Framework, Symfony und natürlich Laravel. Obwohl jedes dieser Frameworks auf ähnlichen Prinzipien basiert und darauf ausgerichtet ist, (im Wesentlichen) dieselben gemeinsamen Probleme zu lösen, liegen ihre Hauptunterschiede in ihrer Implementierung. Jedes von ihnen hat seine eigenen Eigenheiten, was die Lösung von Problemen angeht. Wenn Sie sich den von jedem von ihnen produzierten Code ansehen, werden Sie feststellen, dass es eine ziemlich klare Linie gibt, die sie voneinander trennt. Unserer bescheidenen Meinung nach ist das Laravel-Framework das beste.

Erfahren Sie mehr darüber Unterschied zwischen Laravel und CodeIgniter

So laden Sie Laravel mit Composer herunter und installieren es

HINWEIS Es wird davon ausgegangen, dass auf Ihrem lokalen System bereits eine Kopie von PHP installiert ist. Wenn nicht, können Sie nachlesen, wie Sie es installieren HIER

Composer ist sowohl ein Paket- als auch ein Abhängigkeitsmanager. Um es zu installieren, öffnen Sie ein Terminal und wechseln Sie per CD in ein neues Verzeichnis. Führen Sie diesen Befehl aus:

curl -Ss getcomposer.org/installer | php

Die Ergebnisse dieses Befehls sehen folgendermaßen aus:

Laden Sie Laravel mit Composer herunter und installieren Sie es

Note Ausführlichere Anweisungen zum Einrichten von Laravel finden Sie in der Laravel-Dokumentation HIER.

Sie werden sehen, wie das Skript composer.phar heruntergeladen und kompiliert wird, das wir zur Installation von Laravel verwenden. Obwohl es zahlreiche Möglichkeiten gibt, eine neue Laravel-Anwendung einzurichten, werden wir dies über das Skript Laravel Composer tun. Um dieses Skript zu installieren, führen Sie Folgendes aus:

composer global require laravel/installer

Was etwa so aussehen wird:

Laden Sie Laravel mit Composer herunter und installieren Sie es

Dadurch werden alle Framework-Dateien sowie alle erforderlichen Abhängigkeiten heruntergeladen und installiert. Die Pakete werden im Vendor-Verzeichnis gespeichert. Sobald es heruntergeladen und installiert ist, ist es ganz einfach, den folgenden Befehl einzugeben:

laravel new uploadApp

Die Ausgabe ähnelt der folgenden:

Laden Sie Laravel mit Composer herunter und installieren Sie es

Composer installiert alle Pakete, die Laravel zum Ausführen benötigt. Dies kann einige Minuten dauern, seien Sie also geduldig. Führen Sie anschließend den Befehl ls -al aus, um zu sehen, was installiert wurde.

Hier ist eine kurze Aufschlüsselung der Verzeichnisse in einer gängigen Laravel-Anwendung:

  • app/ : Dies ist der Quellordner, in dem sich unser Anwendungscode befindet. Alle Controller, Richtlinien und Modelle befinden sich in diesem Ordner
  • Bootstrap/ : Enthält das Startskript der Anwendung und einige Klassenzuordnungsdateien
  • config/ : Enthält die Konfigurationsdateien der App. Diese werden normalerweise nicht direkt geändert, sondern basieren auf den Werten, die in der .env-Datei (Umgebung) im Stammverzeichnis der App eingerichtet sind
  • Datenbank/ : Enthält die Datenbankdateien einschließlich Migrationen, Seeds und Testfabriken
  • öffentlich/ : Öffentlich zugänglicher Ordner mit kompilierten Assets und natürlich einer index.php-Datei
  • Ressourcen/: Enthält Front-End-Assets wie Javascript-Dateien, Sprachdateien, CSS/SASS-Dateien und alle in der Anwendung verwendeten Vorlagen (sogenannte Blade-Vorlagen).
  • Routen/ : Alle Routen in der Anwendung sind hier enthalten. Es gibt einige verschiedene „Umfänge“ von Routen, aber wir werden uns auf die web.php-Datei konzentrieren
  • Lagerung/ : Alle von der Anwendung verwendeten temporären Cachedateien, Sitzungsdateien, kompilierten Ansichtsskripts und Protokolldateien
  • Tests/ : Enthält Testdateien für die Anwendung, z. B. Komponententests und Funktionstests.
  • Verkäufer/ : Alle mit Composer installierten Abhängigkeitspakete

Nun erstellen wir den Rest der App und führen sie mit einem speziellen Handwerkerbefehl aus (um uns den Aufwand zu ersparen, einen Webserver wie Apache oder Nginx zu installieren und zu konfigurieren). Die .env-Datei enthält alle Konfigurationswerte, die die Dateien im Verzeichnis /config zum Konfigurieren der Anwendung verwenden. Darin werden Sie feststellen, dass der Konfigurationswert für verschiedene Parameter von den Interna der Anwendung verwendet wird.

Anwendungsdesign: Ein kurzer Überblick über unsere Anforderungen

In diesem Online-Laravel-Tutorial erstellen wir eine sehr einfache Anwendung, die nur zwei Dinge tut:

  1. Datei-Uploads aus einem Webformular verarbeiten
  2. Anzeige der zuvor hochgeladenen Dateien auf einer anderen Seite.

Für dieses Projekt ist unsere Anwendung schreibgeschützt, was bedeutet, dass der Benutzer nur Dateien schreiben und die Liste der Dateien anzeigen kann, die er hochgeladen hat. Diese Anwendung ist äußerst einfach, sollte Ihnen aber als gute Übung dienen, auf der Sie Ihre Laravel-Fähigkeiten und -Kenntnisse aufbauen können. Beachten Sie, dass ich der Kürze halber jegliche Datenbankmodellierung, Migrationen und Authentifizierung ausgeschlossen habe, aber in einer realen Anwendung sind dies zusätzliche Dinge, die Sie berücksichtigen sollten.

Hier ist eine Liste der Komponenten, die wir benötigen, damit die Anwendung wie erwartet funktioniert:

  • A Route Dies ermöglicht der Außenwelt (Internet) die Nutzung der Anwendung und gibt den Endpunkt an, der darauf verweist, wo sich die Logik zum Speichern der hochgeladenen Datei befindet
  • A Controller das den Anfrage-zu-Antwort-Fluss verarbeitet
  • A Vorlage Hiermit werden eine Liste der zuvor hochgeladenen Dateien und das eigentliche Upload-Formular angezeigt
  • A Anforderung die der Verantwortliche zur Validierung der aus dem Webformular übermittelten Daten verwendet

Was ist eine Route?

Eine Route in Laravel ist im Grunde ein durch einen URI spezifizierter Endpunkt, der als „Zeiger“ auf eine von der Anwendung angebotene Funktionalität fungiert. Am häufigsten zeigt eine Route einfach auf eine Methode auf einem Controller und bestimmt auch, welche HTTP-Methoden auf diesen URI zugreifen können. Eine Route bedeutet auch nicht immer eine Controller-Methode. Es könnte auch einfach die Ausführung der Anwendung an einen definierten Abschluss oder eine anonyme Funktion übergeben.

Warum Route verwenden?

Routen werden in Dateien im Ordner /routes im Stammverzeichnis des Projekts gespeichert. Standardmäßig gibt es einige verschiedene Dateien, die den verschiedenen „Seiten“ der Anwendung entsprechen („Seiten“ stammt aus der hexagonalen Architekturmethodik). Dazu gehören:

  • web.php Die öffentlich zugänglichen „browser“-basierten Routen. Diese kommen am häufigsten vor und werden vom Webbrowser angegriffen. Sie laufen über die Web-Middleware-Gruppe und enthalten auch Funktionen für CSRF-Schutz (was zur Abwehr formularbasierter böswilliger Angriffe und Hacks beiträgt) und im Allgemeinen einen gewissen „Status“ enthalten (damit meine ich, dass sie Sitzungen nutzen)
  • api.php Routen, die einer API-Gruppe entsprechen und daher die API-Middleware standardmäßig aktiviert haben. Diese Routen sind zustandslos und haben keine Sitzungen oder anforderungsübergreifenden Speicher (eine Anforderung teilt weder Daten noch Speicher mit einer anderen Anforderung – jede ist selbstgekapselt).
  • console.php Diese Routen entsprechen benutzerdefinierten Handwerkerbefehlen, die Sie für Ihre App erstellt haben
  • channels.php Registriert Routen für die Übertragung von Ereignissen

Die Schlüsseldatei, mit der Sie sich derzeit befassen müssen, ist die browserspezifische Datei web.php. Standardmäßig ist bereits eine Route definiert. Dies ist die Route, die Sie direkt anklicken, wenn Sie zum Webstammverzeichnis Ihrer Anwendung navigieren (das Webstammverzeichnis befindet sich im öffentlichen Verzeichnis). Wir benötigen drei verschiedene Routen, damit unsere Upload-Anwendung funktioniert:

  • /upload Dies ist der URI der Hauptseite, auf der unser Webformular zum Hochladen von Dateien angezeigt wird.
  • /process Dies ist der Ort, an dem das Formular, das sich unter dem /upload-URI befindet, seine vom Formular übermittelten Daten an (die „Aktion“ des Formulars) sendet.
  • /list Hier werden alle auf die Website hochgeladenen Dateien aufgelistet

beachten Der /list-Endpunkt ist möglicherweise nicht erforderlich, wenn wir die gesamte Logik für die Anzeige des Upload-Formulars und der Dateiliste auf einer einzigen Seite unterbringen möchten. Wir haben sie jedoch vorerst getrennt gehalten, um dem jeweiligen Thema etwas mehr Sachverhalt hinzuzufügen .

//inside routes/web.php
Route::get('/upload', 'UploadController@upload')->name('upload');
Route::get('/download, 'UploadController@download)->name(‘download');
Route::post('/process', 'UploadController@process')->name('process');
Route::get('/list', 'UploadController@list')->name('list');

In diesem Laravel-Framework-Tutorial werden wir jede gewünschte Route explizit in der Routendatei web.php auflisten, indem wir eine der verfügbaren HTTP-spezifischen Anforderungsmethoden (get(), post(), put(), delete(), patch() oder options() ). Eine Aufschlüsselung der einzelnen Punkte finden Sie hier fehlen uns die Worte. aus. Diese Methoden geben an, welche HTTP-Verben auf diese bestimmte Route zugreifen dürfen. Wenn Sie eine Route benötigen, die mehr als ein HTTP-Verb akzeptieren kann (was der Fall sein könnte, wenn Sie eine einzelne Seite verwenden, um sowohl die Anfangsdaten anzuzeigen als auch übermittelte Formulardaten zu posten), können Sie Route::any( ) Methode.

Das zweite Argument für die Methoden Route::get() und Route::post() (und alle anderen HTTP-Verb-bezogenen Methoden auf der Route-Fassade) ist der Name eines bestimmten Controllers und einer Methode in diesem Controller, die ausgeführt wird, wenn der Endpunkt der Route mit der zulässigen HTTP-Anforderung (GET, POST, PATCH usw.) erreicht wird. Wir verwenden den UploadController für alle drei Routen und haben sie folgendermaßen angegeben:

Was ist eine Route?

Die letzte Methode, die wir für jede Route aufrufen, ist die Funktion name(), die eine einzelne Zeichenfolge als Argument akzeptiert und dazu dient, eine bestimmte Route mehr oder weniger mit einem leicht zu merkenden Namen zu „kennzeichnen“ (in unseren Fällen hochladen, verarbeiten und auflisten). Mir ist klar, dass es keine so tolle Funktion zu sein scheint, jeder Route einen eigenen Namen zu geben, wenn die URL genau gleich heißt, aber es ist wirklich praktisch, wenn Sie eine bestimmte Route wie /users/profile/dashboard/config haben. was leichter zu merken wäre als „profile-admin“ oder „user-config“.

Ein Hinweis zu Fassaden:

  • Fassaden bieten eine „statische“ Schnittstelle zu Klassen, die im Servicecontainer der Anwendung verfügbar sind.“
  • Sie bieten eine knappe, einprägsame Syntax, die es Ihnen ermöglicht, die Funktionen von Laravel zu nutzen, ohne sich lange Klassennamen merken zu müssen, die manuell eingefügt oder konfiguriert werden müssen.

Bei den obigen Routendefinitionen in diesem Laravel-Framework-Tutorial verwenden wir die Routenfassade, anstatt manuell ein neues Illuminate/Routing/Router-Objekt zu instanziieren und die entsprechenden Methoden für dieses Objekt aufzurufen. Es handelt sich lediglich um eine Verknüpfung, die das Tippen erspart. Fassaden werden im gesamten Laravel-Framework häufig verwendet – Sie können und sollten sich besser mit ihnen vertraut machen. Die Dokumente für Fassaden finden Sie hier HIER.

Was ist ein Controller?

Ein Controller ist das „C“ in der „MVC“-Architektur (Model-View-Controller), auf der Laravel basiert. Die Aufgabe eines Controllers lässt sich auf diese einfache Definition reduzieren: Es empfängt die Anfrage vom Client und gibt eine Antwort an den Client zurück. Dies ist die grundlegende Definition und auch die Mindestanforderungen eines bestimmten Controllers. Was es zwischen diesen beiden Dingen tut, wird im Allgemeinen als „Aktion“ des Controllers (oder als „Route-Implementierung“) betrachtet. Es fungiert als zweiter Zugangspunkt zur Anwendung (der erste ist die Anfrage) für den Client, der die Anfragenutzlast (auf die wir als Nächstes eingehen) an die Anwendung sendet und eine Antwort (in Form einer Antwort) erwartet Erfolgsseite, Weiterleitung, Fehlerseite oder jede andere Art von HTTP-Antwort).

Ein Controller macht (im Grunde) dasselbe wie eine Routendefinition mit einer anonymen Funktion, die als „Aktion“ festgelegt wird, wenn diese Route erreicht wird. Der Unterschied besteht darin, dass ein Controller der Trennung von Belangen gut standhält, während eine Route inline zur tatsächlichen URL-Definition definiert wird, was im Grunde bedeutet, dass wir den zugewiesenen URI der Route mit der Implementierung der Route oder dem Code koppeln, der ausgeführt wird, wenn diese Route vorhanden ist Schlag.

Beispielsweise erreichen die folgenden beiden Codeteile dasselbe:

Beispiel Nr. 1: Definition und Implementierung der Route innerhalb eines einzelnen Methodenaufrufs (in der Routendatei web.php)

//inside routes/web.php
<?php
Route::get('/hello-world', function(Request $request) {
   $name = $request->name;
   return response()->make("<h1>Hello World! This is ".$name, 200);
});

Beispiel Nr. 2: Die Definition der Route befindet sich in „routes/web.php“, die Implementierung befindet sich jedoch in der Klasse „/app/Http/Controllers/HelloWorldController“.

//inside routes/web.php
<?php

Route::get('/hello-world', 'HelloWorldController@index')->name('hello-world');

------------------------------------------------------------------------------------
//inside app/Http/Controllers/HelloWorldController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;

class HelloWorldController extends Controller
{
   public function index(Request $request)
   {
       $name = $request->name;
       return response()->make("<h1>Hello World! This is ".$name, 200);
   }
}

Obwohl Laravel-Beispiel Nr. 2 viel mehr Arbeit zu sein scheint (was es nicht ist – nur ein bisschen mehr Code ist alles), sehen Sie sich die Vorteile an, die wir erzielen, wenn wir unsere Aktionslogik für die gegebene „Hallo-Welt“-Route stattdessen in einen Controller integrieren mit der Definition der Route als Callback-Funktion:

  1. Unsere Logik ist sauber in eine eigene Klasse getrennt (Separation of Concerns)
  2. Unser Controller ist für eine spätere Erweiterung eingerichtet, falls wir ihm zusätzliche Funktionen hinzufügen möchten. Nehmen wir an, wir möchten eine „Goodbye-World“-Funktion hinzufügen. In diesem Fall würden wir den Controller in ein allgemeineres „HelloController“ umbenennen und dann zwei separate Methoden definieren. Hallo() und Verabschiedung(). Wir müssten auch zwei separate Routen definieren, die das abbilden /Hallo und / Auf Wiedersehen URIs zu ihrer entsprechenden Methode auf dem Controller. Dies ist wünschenswert im Vergleich zum Auffüllen einer Routendatei, bei der die Implementierung jeder Route als Rückruffunktionen definiert ist.
  3. Laravel verfügt über die integrierte Fähigkeit, alle Routendefinitionen in der Anwendung zwischenzuspeichern, sodass die Zeit zum Auffinden einer bestimmten Route verkürzt wird (und die Anwendungsleistung erhöht wird). jedoch Sie können davon nur profitieren, wenn alle Ihre definierten Routen innerhalb der Anwendung mithilfe von Controller-spezifischen Zuordnungen konfiguriert sind (siehe Beispiel Nr. 2 oben).

Lassen Sie uns diesen Befehl ausführen, der einen neuen Controller für uns generiert.

// ...inside the project's root directory:
php artisan make:controller UploadController   

Im Wesentlichen generiert dieser Befehl einen Stub für einen Controller namens „UploadController“ im Haupt-Controller-Verzeichnis unter /app/Http/Controllers/UploadController.php. Sie können diese Datei gerne öffnen und einen Blick darauf werfen. Es ist sehr einfach, da es sich nur um eine Stub-Out-Version des Controllers mit dem richtigen Namespace-Pfad und den erforderlichen Klassen handelt, von denen aus er erweitert wird.

Generieren der Anfrage

Bevor wir in diesem PHP Laravel-Tutorial fortfahren und ein paar Änderungen am generierten Stub des UploadControllers vornehmen, halte ich es für sinnvoller, zuerst die Anforderungsklasse zu erstellen. Dies liegt daran, dass die Controller-Methode, die die Anforderung verarbeitet, in ihrer Signatur einen Typhinweis auf das Anforderungsobjekt geben muss, damit die eingehenden Formulardaten automatisch validiert werden können (wie in der Methode rules() angegeben. Mehr dazu später …). Lassen Sie uns zunächst erneut den Artisan-Befehl verwenden, um unseren Anforderungs-Stub zu generieren:

php artisan make:request UploadFileRequest

Dieser Befehl generiert eine Datei namens UploadFileRequest in app/Http/Requests/UploadFileRequest. Öffnen Sie den Stub und werfen Sie einen Blick darauf … Sie werden feststellen, dass er sehr einfach ist und nur zwei Methoden enthält: „authorize()“ und „rules“.

Erstellen der Validierungslogik

Ändern wir den Anforderungs-Stub, um ihn an die Anforderungen unserer Anwendung anzupassen. Ändern Sie die Datei so, dass sie wie folgt aussieht:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class UploadFileRequest extends FormRequest
{
   /**
    * Determine if the user is authorized to make this request.
    *
    * @return bool
    */
   public function authorize()
   {
       return true;
   }

   /**
    * Get the validation rules that apply to the request.
    *
    * @return array
    */
   public function rules()
   {
       return [
           'fileName' => 'required|string',
           'userFile' => 'required|file'
       ];
   }
}

Es gibt nicht viele Änderungen, aber beachten Sie, dass die Methode „authorize()“ jetzt „true“ statt „false“ zurückgibt. Diese Methode entscheidet, ob die Anforderung in die Anwendung aufgenommen werden darf oder nicht. Wenn es auf „false“ gesetzt ist, verhindert es, dass die Anforderung in das System gelangt (was normalerweise eine Methode auf dem Controller wäre). Dies wäre ein sehr praktischer Ort, um Autorisierungsprüfungen für den Benutzer oder eine andere Logik durchzuführen, die entscheiden könnte, ob die Anfrage an den Controller weitergeleitet werden kann. Im Moment geben wir hier einfach „true“ zurück, um allen und jedem die Möglichkeit zu geben, die Anfrage zu verwenden.

Bei der anderen Methode, Rules(), kommt die ganze Magie im Hinblick auf die Validierung ins Spiel. Die Idee ist einfach: Geben Sie ein Array zurück, das eine Reihe von Regeln enthält, in der Form:

'formFieldName' => 'constraints this field has separated by pipe characters (|)'

Es gibt viele verschiedene Validierungsbeschränkungen, die von Laravel sofort unterstützt werden. Eine vollständige Liste finden Sie in der Online-Dokumentation. HIER. Für unsere Upload-Anwendung gibt es zwei Felder, die per POST-Anfrage von einem Formular im Frontend übergeben werden. Der Parameter fileName muss im Formulartext enthalten sein (d. h. erforderlich) und wird als Dateiname verwendet, unter dem wir die Datei im Speicher ablegen (dies geschieht im Controller – wir kommen etwas später darauf zurück). Wir geben auch an, dass der Dateiname eine Zeichenfolge sein muss, indem wir ein Pipe-Zeichen (|) und das Wort „String“ hinzufügen. Einschränkungen werden immer durch Pipes abgegrenzt, sodass Sie in einer einzigen Zeile zusätzliche Kriterien für das angegebene Feld angeben können! Was für eine Leistung!

Der zweite Parameter, userFile , ist die tatsächliche Datei, die der Benutzer aus einem Formular auf einer Webseite hochlädt. UserFile ist ebenfalls erforderlich und sollen eine Datei sein. Hinweis: Wenn wir davon ausgehen würden, dass es sich bei der hochgeladenen Datei um ein Bild handelt, würden wir stattdessen die Bildbeschränkung verwenden, die die akzeptierten Dateitypen auf einen der gängigen Bildtypen (JPEG, PNG, BMP, GIF oder SVG) beschränken würde. Da wir dem Benutzer das Hochladen aller Dateitypen ermöglichen möchten, bleiben wir bei der Dateivalidierungsbeschränkung.

Das ist ungefähr alles, was das Anforderungsobjekt zu bieten hat. Seine Hauptaufgabe besteht einfach darin, die akzeptablen Kriterien (Einschränkungen) festzuhalten, die die Körperparameter des Formulars erfüllen müssen, um tiefer in die Anwendung vorzudringen. Beachten Sie außerdem, dass diese beiden Felder (userFile und filename) auch im HTML-Code in Form von Eingabefeldern angegeben werden müssen (wobei der Feldname dem Namen im Anforderungsobjekt entspricht).

Sie fragen sich vielleicht: Dies definiert sicher die Merkmale dessen, was eine Formularanforderung enthalten sollte, aber wo wird die eigentliche Prüfung dieser Einschränkungen durchgeführt? Wir werden als nächstes darauf eingehen.

Ändern des Controllers

Öffnen Sie app/Http/Controllers/UploadController und nehmen Sie die folgenden Änderungen vor:

<?php

namespace App\Http\Controllers;

use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Http\Request;
use App\Http\Requests\UploadFileRequest; //our new request class
use Illuminate\Support\Facades\Storage; 

class UploadController extends Controller
{
   /**
    * This is the method that will simply list all the files uploaded by name and provide a
    * link to each one so they may be downloaded
    *
    * @param $request : A standard form request object
    * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
    * @throws BindingResolutionException
    */
   public function list(Request $request)
   {
       $uploads = Storage::allFiles('uploads');

       return view('list', ['files' => $uploads]);
   }

   /**
    * @param $file
    * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
    * @throws BindingResolutionException
    */
   public function download($file)
   {
       return response()->download(storage_path('app/'.$file));
   }

   /**
    * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
    * @throws BindingResolutionException
    */
   public function upload()
   {
       return view('upload');
   }

   /**
    * This method will handle the file uploads. Notice that the parameter's typehint
    * is the exact request class we generated in the last step. There is a reason for this!
    *
    * @param $request : The special form request for our upload application
    * @return array|\Illuminate\Http\UploadedFile|\Illuminate\Http\UploadedFile[]|null
    * @throws BindingResolutionException
    */
   public function store(UploadFileRequest $request)
   {
       //At this point, the parameters passed into the $request (from form) are
       //valid--they satisfy each of the conditions inside the rules() method

       $filename = $request->fileName;    //parameters have already been validated
       $file = $request->file('userFile'); //that we don't need any additional isset()

       $extension = $file->getClientOriginalExtension(); //grab the file extension
       $saveAs = $filename . "." . $extension; //filename to save file under

       $file->storeAs('uploads', $saveAs, 'local'); //save the file to local folder

       return response()->json(['success' => true]); //return a success message
   }
}

Es handelt sich also um einen recht einfachen Ansatz zum Speichern der hochgeladenen Dateien auf der Festplatte. Hier ist eine Aufschlüsselung der obigen Methode upload():

  • Geben Sie einen Hinweis auf die Anforderungsklasse in der Controller-Methode ein, die die Funktionalität „Fleisch und Kartoffeln“ ausführt, damit wir die eingehenden Daten automatisch validieren können
  • Holen Sie sich die Datei aus dem (jetzt validierten) Anforderungsobjekt innerhalb der Controller-Methode (in diesem Fall haben wir sie upload() genannt, sie hätte aber auch einen standardisierteren Namen wie store() erhalten können).
  • Nehmen Sie den Dateinamen aus der Anfrage heraus
  • Generieren Sie den endgültigen Dateinamen, der zum Speichern der Datei verwendet wird. Die Methode getClientOriginalExtension() greift einfach auf die ursprüngliche Erweiterung der hochgeladenen Datei zurück.
  • Speichern Sie die Datei mit der Methode „storeAs()“ im lokalen Dateisystem und übergeben Sie dabei den benannten Pfad im Verzeichnis /storage als erstes Argument und den Dateinamen, unter dem sie gespeichert werden soll, als zweites.
  • Geben Sie eine JSON-Antwort zurück, die angibt, dass die Anfrage erfolgreich war

Die Blade-Vorlage

Das letzte große Teil dieses Puzzles ist die Blade-Vorlage, die alle HTML-, CSS- und JavaScript-Elemente für unsere einfache Anwendung enthält. Hier ist der Code – wir werden ihn später erklären.

<body>
   <h1>Upload a file</h1>
   <form id="uploadForm" name="uploadForm" action="{{route('upload')}}" enctype="multipart/form-data">
       @csrf
       <label for="fileName">File Name:</label>
       <input type="text" name="fileName" id="fileName" required /><br />
       <label for="userFile">Select a File</label>
       <input type="file" name="userFile" id="userFile" required />
       <button type="submit" name="submit">Submit</button>
   </form>
   <h2 id="success" style="color:green;display:none">Successfully uploaded file</h2>
   <h2 id="error" style="color:red;display:none">Error Submitting File</h2>
   <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
   <script>
        $('#uploadForm').on('submit', function(e) {
            e.preventDefault();
            var form = $(this);
            var url = form.attr('action');
            $.ajax({
                url: url,
                type: "POST",
                data: new FormData(this),
                processData: false,
                contentType: false,
                dataType: "JSON",
                success: function(data) {
                    $("#fileName").val("");
                    $("#userFile").val("");
                }
            }).done(function() {
                $('#success').css('display', 'block');
                window.setTimeout(()=>($("#success").css('display', 'none')), 5000);
            }).fail(function() {
                $('#error').css('display', 'block');
                window.setTimeout(()=>($("#error").css('display', 'none')), 5000);
            });
        });
   </script>
</body>
</html>

Hier ist, was unser / Hochladen Seite sieht so aus:

Die Blade-Vorlage

Dies ist ein sehr typisches Beispiel für eine Blade-Datei, die ein HTML-Formular und JavaScript/jQuery zum Hinzufügen asynchroner Funktionen enthält (damit die Seite nicht aktualisiert wird). Es gibt eine grundlegende Tag ohne Methodenattribut (das ich gleich erklären werde) und mit einem merkwürdigen Aktionsattribut mit dem Wert {{route('file.upload')}}. In Blade ist dies das, was als Richtlinie. Eine Direktive ist nur ein schicker Name für eine Funktion – es sind Funktionen, die spezifisch für Blade-Vorlagen sind und verschiedene Operationen ausführen, die beim Erstellen von Webseiten und Webanwendungen üblich sind. Um besser zu verstehen, was Blade alles kann, lesen Sie die Dokumentation HIER. Im obigen Fall verwenden wir die Route-Direktive, um eine URL für die Übermittlung unseres Formulars zu generieren.

Denken Sie daran, dass wir unsere Routen bereits früher in der Anwendung in der Datei web.php definiert und für jede Route einen leicht zu merkenden Namen angegeben haben. Die {{route()}}-Direktive akzeptiert den Namen einer Route, sucht ihn in der intern zwischengespeicherten Routenliste und generiert eine vollständige URL basierend auf der Definition dieser Route in der Datei web.php. Für diesen ersten Fall geben wir an, dass das Formular seine übermittelten Daten an die /process-URL unserer Anwendung senden soll, die als definiert ist jetzt lesen Route.

Die nächste seltsame Sache, die Ihnen vielleicht aufgefallen ist, ist das @csrf-Tag direkt unter dem öffnenden Formular-Tag. In Blade generiert dieses Tag einen _token-Parameter im Formular, der in der Anwendung überprüft wird, bevor die Formulardaten verarbeitet werden dürfen. Dadurch wird sichergestellt, dass die Daten im Formular einen gültigen Ursprung haben und Cross-Site-Request-Forgery-Angriffe verhindert werden. Weitere Informationen hierzu finden Sie unter docs.

Danach definieren wir unser Formular wie gewohnt. Beachten Sie jedoch, dass die Namen unserer Formularparameter userFile und fileName lauten genau die gleiche wie in unserem Anforderungsobjekt definiert. Wenn wir vergessen hätten, eine Eingabe für einen bestimmten Parameter einzufügen, der im Anforderungsobjekt definiert war (oder ihn falsch geschrieben hätten), würde die Anforderung fehlschlagen und ein Fehler zurückgegeben werden, wodurch verhindert würde, dass die ursprüngliche Formularanforderung jemals die Controller-Methode unter UploadController@ erreicht. Verfahren .

Probieren Sie es einfach aus und reichen Sie mit diesem Formular ein paar Dateien bei der Bewerbung ein. Navigieren Sie anschließend zu /aufführen Seite, um den Inhalt des Upload-Ordners anzuzeigen. Die von Ihnen hochgeladenen Dateien werden in einer Tabelle aufgelistet:

Die Blade-Vorlage

The Bigger Picture

Machen wir einen Schritt zurück und schauen uns an, was wir in diesem Laravel-Tutorial gemacht haben.

Dieses Diagramm zeigt die Anwendung in ihrem aktuellen Zustand (ohne nähere Einzelheiten):

Laravel-Tutorial-Diagramm

Sie sollten sich daran erinnern, dass das Anforderungsobjekt, das wir zu Beginn dieses Laravel-Tutorials erstellt haben, in seiner Regelmethode dieselben Parameter haben sollte wie im Formular in der Blade-Vorlage (falls nicht, lesen Sie den Abschnitt „Erstellen der Validierungslogik“ noch einmal). . Der Benutzer gibt das Formular auf einer Webseite ein, die über eine Blade-Template-Engine gerendert wird (dieser Vorgang erfolgt natürlich auf Autopilot, sodass wir nicht einmal darüber nachdenken müssen) und sendet das Formular ab. Der jQuery-Code der Vorlage unten stoppt die Standardübermittlung (die automatisch auf eine separate Seite umleiten würde), erstellt eine Ajax-Anfrage, lädt die Anfrage mit den Formulardaten und lädt die Datei hoch und sendet das Ganze an die erste Ebene unseres Anwendung: die Anfrage.

Das Anforderungsobjekt wird gefüllt, indem die Parameter innerhalb der Rules()-Methode mit den übermittelten Formularparametern verknüpft werden und anschließend die Daten gemäß jeder angegebenen Regel validiert werden. Wenn alle Regeln erfüllt sind, wird die Anfrage an die Controller-Methode weitergeleitet, die den in der Routendatei web.php definierten Werten entspricht. In diesem Fall ist es die Methode „process()“ des UploadControllers, die die Arbeit erledigt. Sobald wir den Controller erreichen, wissen wir bereits, dass die Anforderung die Validierung bestanden hat, sodass wir nicht erneut testen müssen, ob der angegebene Dateiname tatsächlich eine Zeichenfolge ist oder der Parameter „userFile“ tatsächlich einen Dateityp enthält … Wir können wie folgt fortfahren normal.

Die Controller-Methode ruft dann die validierten Parameter aus dem Anforderungsobjekt ab, generiert einen vollständigen Dateinamen, indem sie den übergebenen fileName-Parameter mit der ursprünglichen Erweiterung von userFile verkettet, speichert die Datei in einem Verzeichnis in unserer Anwendung und gibt dann eine einfache JSON-codierte Datei zurück Antwort, die bestätigt, dass die Anfrage erfolgreich war. Die Antwort wird von der jQuery-Logik empfangen, die einige weitere UI-bezogene Aufgaben ausführt, z. B. die Erfolgs- (oder Fehlermeldung) fünf Sekunden lang anzuzeigen und sie dann auszublenden sowie die vorherigen Formulareinträge zu löschen … damit der Benutzer Bescheid weiß Stellen Sie sicher, dass die Anfrage erfolgreich war, und können Sie bei Bedarf eine weitere Datei hochladen.

Beachten Sie auch, wo im obigen Diagramm die Linie zwischen Client und Server verläuft. Dieses Konzept ist für Sie unbedingt zu verstehen und wird Ihnen helfen, Probleme und Schwierigkeiten zu lösen, die in Zukunft auftreten können, wenn Sie beispielsweise mit mehreren asynchronen Anfragen jonglieren, die jederzeit auftreten können. Die Trennung erfolgt direkt an der Grenze des Anfrageobjekts. Das Anfrageobjekt selbst kann als „Gateway“ zum Rest der Anwendung betrachtet werden … Es führt die anfängliche Validierung und Registrierung der vom Webbrowser übermittelten Formularwerte durch. Wenn sie als gültig erachtet werden, geht es weiter zum Controller. Alles davor befindet sich auf der Frontend-Seite (der „Client“ bedeutet wörtlich „auf dem Computer des Benutzers“). Die Antwort wird von der App zurück an die Client-Seite gesendet, wo unser jQuery-Code geduldig auf ihr Eintreffen wartet und nach Erhalt einige einfache UI-Aufgaben ausführt.

Wir haben fast 90+ wichtige, häufig gestellte Fragen behandelt Interviewfragen zu Laravel und PHP sowohl für Berufseinsteiger als auch für erfahrene Kandidaten, den richtigen Job zu finden.