Laravel-tutorial voor beginners

Wat is Laravel?

Laravel is een open-source web-MVC-framework voor PHP. Laravel is een robuust raamwerk dat de eenvoudige ontwikkeling van PHP-webapplicaties mogelijk maakt met functies zoals een modulair verpakkingssysteem met een speciale afhankelijkheidsmanager, toegang tot relationele databases en andere hulpprogramma's voor de implementatie en het onderhoud van applicaties.

Laravel is gemaakt door Taylor Otwell. Sinds de eerste release in juni 2011 (versie 1) is het gestaag steeds populairder geworden in de PHP-frameworksector van de webontwikkelingsindustrie. Een groot deel van deze populariteit kan worden toegeschreven aan de vele op ontwikkelaars gerichte functies die standaard worden meegeleverd.

Waarom Laravel?

Circa 2000, meest PHP-codes was procedureel en kon worden gevonden in de vorm van ‘scripts’ die een wirwar van spaghetticode zouden bevatten. Zelfs de eenvoudigste pagina's hadden geen scheiding van zorgen, en daardoor kon een applicatie vrij gemakkelijk uitgroeien tot een onderhoudsnachtmerrie. De wereld had iets beters nodig... Voer PHP versie 5 in en een verscheidenheid aan PHP-frameworks die proberen de broodnodige resolutie en betere oplossingen te bieden voor verschillende problemen met webapplicaties.

Sindsdien hebben we veel frameworks uitgebracht die de weg vrijmaakten voor de populaire frameworks die vandaag de dag bestaan ​​en worden gebruikt. De top drie zou (naar onze mening) Zend Framework, Symfony en natuurlijk Laravel zijn. Hoewel elk van deze frameworks is gebaseerd op vergelijkbare principes en gericht is op het oplossen van (in principe) dezelfde veelvoorkomende problemen, liggen de belangrijkste verschillen in hun implementaties. Ze hebben elk hun eigen eigenaardigheden over hoe je problemen oplost. Wanneer je kijkt naar de code die door elk van hen is geproduceerd, zul je zien dat er een vrij stevige lijn is die ze van elkaar scheidt. Naar onze bescheiden mening is het Laravel-framework het beste.

Lees verder over Verschil tussen Laravel en CodeIgniter

Hoe Laravel downloaden en installeren met Composer

NOTITIE Er wordt aangenomen dat u al een exemplaar van PHP op uw lokale systeem hebt geïnstalleerd. Zo niet, dan kun je lezen hoe je deze installeert hier

Composer is zowel een pakket- als afhankelijkheidsbeheerder. Om het te installeren, opent u een terminal en cd naar een nieuwe directory. Voer deze opdracht uit:

curl -Ss getcomposer.org/installer | php

De resultaten van deze opdracht zien er als volgt uit:

Download en installeer Laravel met Composer

Note Voor uitgebreidere instructies over het instellen van Laravel raadpleegt u de Laravel-documentatie hier.

Je zult zien dat het het composer.phar script downloadt en compileert, wat we gebruiken om Laravel te installeren. Hoewel er talloze manieren zijn om een ​​nieuwe Laravel applicatie op te zetten, zullen we dit doen via het Laravel composer script. Om dit script te installeren, voer je het volgende uit:

composer global require laravel/installer

Wat er ongeveer zo uit zal zien:

Download en installeer Laravel met Composer

Dit zal alle frameworkbestanden zelf downloaden en installeren, evenals alle afhankelijkheden die het nodig heeft. De pakketten worden opgeslagen in de leveranciersmap. Zodra het is gedownload en geïnstalleerd, is het net zo eenvoudig als het uitgeven van de volgende opdracht:

laravel new uploadApp

U zult iets zien dat lijkt op het volgende resultaat:

Download en installeer Laravel met Composer

Composer installeert alle pakketten die Laravel nodig heeft om te kunnen draaien. Het kan een paar minuten duren, dus wees geduldig. Nadat het klaar is, voer je een ls -al commando uit om te kijken wat er is geïnstalleerd.

Hier is een kort overzicht van de mappen in een veelgebruikte Laravel-applicatie:

  • app/ : Dit is de bronmap waarin onze applicatiecode zich bevindt. Alle controllers, beleidsregels en modellen bevinden zich in deze map
  • bootstrap/ : Bevat het opstartscript van de applicatie en een paar klassentoewijzingsbestanden
  • configuratie/: Bevat de configuratiebestanden van de app. Deze worden meestal niet rechtstreeks gewijzigd, maar vertrouwen in plaats daarvan op de waarden die zijn ingesteld in het .env-bestand (omgeving) in de hoofdmap van de app
  • databank/ : Bevat de databasebestanden, inclusief migraties, zaden en testfabrieken
  • openbaar/ : Openbaar toegankelijke map met gecompileerde assets en natuurlijk een index.php-bestand
  • bronnen/ : Bevat front-end assets zoals javascript-bestanden, taalbestanden, CSS/SASS-bestanden en alle sjablonen die in de applicatie worden gebruikt (zogenaamde blade-sjablonen)
  • trajecten/ : Alle routes in de applicatie staan ​​hier binnen. Er zijn een paar verschillende “scopes” van routes, maar degene waar we ons op zullen concentreren is het web.php-bestand
  • opslag/ : Alle tijdelijke cachebestanden die door de applicatie worden gebruikt, sessiebestanden, gecompileerde weergavescripts en logbestanden
  • testen/ : Bevat testbestanden voor de applicatie, zoals unittests en functionele tests.
  • leverancier/ : Alle afhankelijkheidspakketten geïnstalleerd met composer

Laten we nu de rest van de app bouwen en deze uitvoeren met een speciaal ambachtelijk commando (om onszelf de moeite te besparen van het installeren en configureren van een webserver zoals Apache of nginx). Het .env-bestand bevat alle configuratiewaarden die de bestanden in de directory /config gebruiken om de applicatie te configureren. Daarin zul je merken dat de configuratiewaarde voor verschillende parameters wordt gebruikt door de interne onderdelen van de applicatie.

Applicatieontwerp: een kort overzicht van onze vereisten

In deze online Laravel-tutorial gaan we een heel eenvoudige applicatie bouwen die slechts twee dingen doet:

  1. bestandsuploads vanaf een webformulier afhandelen
  2. het weergeven van de eerder geüploade bestanden op een andere pagina.

Voor dit project zal onze applicatie alleen-schrijven zijn, wat betekent dat de gebruiker alleen bestanden kan schrijven en de lijst met bestanden kan bekijken die hij of zij heeft geüpload. Deze applicatie is uiterst eenvoudig, maar zou als een goede oefening moeten dienen om je Laravel-vaardigheden en kennis op te bouwen. Merk op dat ik omwille van de beknoptheid alle databasemodellering, migraties en authenticatie heb uitgesloten, maar in een echte toepassing zijn dit aanvullende dingen die u in overweging wilt nemen.

Hier is een lijst met componenten die we nodig hebben om de applicatie te laten werken zoals verwacht:

  • A route waarmee de buitenwereld (internet) de applicatie kan gebruiken en het eindpunt kan specificeren dat verwijst naar waar de logica voor het opslaan van het geüploade bestand zich bevindt
  • A controleur die de request-to-response-stroom afhandelt
  • A sjabloon dat zal worden gebruikt om een ​​lijst met eerder geüploade bestanden en het daadwerkelijke uploadformulier zelf weer te geven
  • A te vragen die de verwerkingsverantwoordelijke zal gebruiken om de gegevens die vanuit het webformulier worden doorgegeven, te valideren

Wat is een route?

Een route in Laravel is in feite een eindpunt dat wordt gespecificeerd door een URI die fungeert als een “pointer” naar een stukje functionaliteit dat door de applicatie wordt aangeboden. Meestal verwijst een route eenvoudigweg naar een methode op een controller en dicteert ook welke HTTP-methoden die URI kunnen bereiken. Een route betekent ook niet altijd een controllermethode; het zou de uitvoering van de applicatie ook gewoon kunnen doorgeven aan een gedefinieerde sluitings- of anonieme functie.

Waarom Route gebruiken?

Routes worden opgeslagen in bestanden onder de map /routes in de rootdirectory van het project. Standaard zijn er een paar verschillende bestanden die overeenkomen met de verschillende "zijden" van de applicatie ("zijden" komt van de hexagonale architectuurmethodologie). Deze omvatten:

  • web.php De openbare “browser”-gebaseerde routes. Dit zijn de meest voorkomende en worden door de webbrowser getroffen. Ze lopen via de webmiddlewaregroep en bevatten ook faciliteiten voor csrf-bescherming (die helpt bij de verdediging tegen op formulieren gebaseerde kwaadaardige aanvallen en hacks) en bevatten over het algemeen een zekere mate van ‘status’ (hiermee bedoel ik dat ze gebruik maken van sessies)
  • api.php Routes die overeenkomen met een API-groep en waarbij de API-middleware dus standaard is ingeschakeld. Deze routes zijn staatloos en hebben geen sessies of kruisverzoekgeheugen (één verzoek deelt geen gegevens of geheugen met enig ander verzoek; elk verzoek is zelf ingekapseld).
  • console.php Deze routes komen overeen met aangepaste ambachtelijke opdrachten die u voor uw app heeft gemaakt
  • channels.php Registreert routes voor uitzending van evenementen

Het sleutelbestand waar we ons op dit moment zorgen over moeten maken is het browserspecifieke bestand, web.php. Er is standaard al één route gedefinieerd, en dat is de route die u rechts aanklikt wanneer u naar de webroot van uw applicatie navigeert (de webroot bevindt zich in de openbare map). We hebben drie verschillende routes nodig om onze uploadapplicatie te laten functioneren:

  • /upload Dit is de URI van de hoofdpagina waarop ons webformulier wordt weergegeven voor het uploaden van bestanden.
  • /process Dit is waar het formulier op de /upload URI de door het formulier ingediende gegevens plaatst (de "actie" van het formulier).
  • /list Hier worden alle bestanden weergegeven die naar de site zijn geüpload

nota Het /list-eindpunt is misschien niet nodig als we alle logica voor het weergeven van het uploadformulier en de lijst met bestanden op één pagina willen plaatsen, maar we hebben ze voorlopig gescheiden gehouden om wat meer materie aan het onderwerp toe te voegen .

//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 deze Laravel-framework-tutorial zullen we voor elke gewenste route deze expliciet vermelden in het routesbestand web.php met behulp van een van de beschikbare HTTP-specifieke verzoekmethoden (get(), post(), put() , delete(), patch() of opties() ). Voor een overzicht van elk van deze, kijk op dit uit. Wat deze methoden doen, is specificeren welke HTTP-werkwoorden toegang hebben tot die bepaalde route. Als u een route nodig heeft om meer dan één HTTP-werkwoord te kunnen accepteren (wat het geval kan zijn als u een enkele pagina gebruikt om zowel de initiële gegevens weer te geven als de ingediende formuliergegevens te posten), kunt u de Route::any( ) methode.

Het tweede argument voor zowel de Route::get()- als de Route::post()-methode (en alle andere HTTP-werkwoordgerelateerde methoden op de Route-facade) is de naam van een specifieke controller en methode die zich in die controller bevindt en die wordt uitgevoerd wanneer het eindpunt van de route wordt bereikt met de toegestane HTTP-aanvraag (GET, POST, PATCH, enz.). We gebruiken de UploadController voor alle drie de routes en hebben deze op de volgende manier gespecificeerd:

Wat is een traject

De laatste methode die we bij elke route aanroepen is de functie name(), die een enkele string als argument accepteert en wordt gebruikt om een ​​bepaalde route min of meer te ‘taggen’ met een gemakkelijk te onthouden naam (in ons geval uploaden, verwerken en weergeven). Ik realiseer me dat het niet zo'n geweldige functie lijkt om elke route een eigen naam te geven als de URL exact dezelfde naam heeft, maar het komt echt van pas als je een specifieke route hebt, zoals /users/profile/dashboard/config, wat gemakkelijker te onthouden zou zijn als profile-admin of user-config.

Een opmerking over gevels:

  • Gevels bieden een “statische” interface voor klassen die beschikbaar zijn in de servicecontainer van de applicatie.”
  • Ze bieden een beknopte, gedenkwaardige syntaxis waarmee u de functies van Laravel kunt gebruiken zonder lange klassenamen te onthouden die handmatig moeten worden geïnjecteerd of geconfigureerd.

Bij de bovenstaande routedefinities in deze Laravel-framework-tutorial gebruiken we de Route-façade in plaats van handmatig een nieuw Illuminate/Routing/Router-object te instantiëren en de bijbehorende methoden op dat object aan te roepen. Het is gewoon een snelkoppeling die typen bespaart. Gevels worden in het Laravel-framework intensief gebruikt; je kunt en moet er meer vertrouwd mee raken. De documentatie voor Gevels kunt u vinden hier.

Wat is een controleur?

Een controller is de “C” in de “MVC” (Model-View-Controller) architectuur, waarop Laravel is gebaseerd. De taak van een controller kan worden samengevat in deze simpele definitie: Het ontvangt het verzoek van de klant en stuurt een antwoord terug naar de klant. Dit is de naakte definitie en tevens de minimumvereisten voor een bepaalde controller. Wat het tussen deze twee dingen doet, wordt over het algemeen beschouwd als de “actie” van de beheerder (of de “implementatie van de route”). Het fungeert als het tweede toegangspunt tot de applicatie (het eerste is het verzoek) voor de klant, die de payload van het verzoek (waar we hierna op zullen terugkomen) naar de applicatie stuurt, in afwachting van een soort antwoord (in de vorm van een succespagina, omleiding, foutpagina of een ander soort HTTP-antwoord).

Een controller doet (in principe) hetzelfde als een routedefinitie met een anonieme functie ingesteld als de “actie” wanneer die route wordt geraakt. Het verschil is dat een controller goed standhoudt in de scheiding van zorgen, terwijl een route inline wordt gedefinieerd op basis van de daadwerkelijke URL-definitie, wat in feite betekent dat we de toegewezen URI van de route koppelen aan de implementatie van de route, of de code die wordt uitgevoerd wanneer die route wordt uitgevoerd. hit.

De volgende twee stukjes code bereiken bijvoorbeeld hetzelfde:

Voorbeeld #1: Routedefinitie en -implementatie binnen een enkele methodeaanroep (in het web.php routesbestand)

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

Voorbeeld #2: De definitie van route bevindt zich in routes/web.php, maar de implementatie ervan bevindt zich in de 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);
   }
}

Hoewel Laravel-voorbeeld nr. 2 veel meer werk lijkt (wat het niet is – alleen een beetje meer code is alles), kijk dan eens naar de voordelen die we behalen door onze actielogica voor de gegeven “hallo-wereld”-route in plaats daarvan in een controller te plaatsen van met de definitie van de route als een callback-functie:

  1. Onze logica is netjes gescheiden in zijn eigen klasse (scheiding van zorgen)
  2. Onze controller is ingesteld voor latere uitbreiding, mocht het nodig zijn om er extra mogelijkheden aan toe te voegen... Stel dat we een "goodbye-world"-functie willen toevoegen... In dat geval zouden we de controller hernoemen naar een meer generieke "HelloController" en vervolgens twee afzonderlijke methoden definiëren, Hallo() en tot ziens(). We zouden ook twee afzonderlijke routes moeten definiëren die de route in kaart brengen /Hallo en / tot ziens URI's naar de juiste methode op de controller. Dit is wenselijk vergeleken met het vetmesten van een routesbestand waarbij de implementatie van elke route is gedefinieerd als callback-functies.
  3. Laravel heeft de ingebouwde mogelijkheid om alle routedefinities in de applicatie in de cache op te slaan, zodat het de tijd versnelt die nodig is om een ​​bepaalde route te vinden (verhoogt de applicatieprestaties); echter u kunt hier alleen van profiteren als al uw gedefinieerde routes binnen de applicatie zijn geconfigureerd met behulp van controllerspecifieke toewijzingen (zie Voorbeeld #2 hierboven)

Laten we deze opdracht uitvoeren die een nieuwe controller voor ons zal genereren.

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

Wat deze opdracht in wezen doet, is een stub genereren voor een controller met de naam "UploadController" in de hoofdcontrollermap op /app/Http/Controllers/UploadController.php. Open dat bestand gerust en kijk er eens naar. Het is heel eenvoudig omdat het slechts een uitgeklede versie van de controller is, met het juiste naamruimtepad en de vereiste klassen waaruit het voortkomt.

Het genereren van het verzoek

Voordat we verdergaan in deze PHP Laravel tutorial en een paar wijzigingen aanbrengen in de gegenereerde stub van de UploadController, denk ik dat het logischer is om eerst de request class te maken. Dit komt omdat de controller methode die de request afhandelt het request object in zijn signature moet type hinten, waardoor het automatisch de binnenkomende form data kan valideren (zoals gespecificeerd in de rules() methode. Meer daarover later…) Laten we voor nu de artisan opdracht opnieuw gebruiken om onze request stub te genereren:

php artisan make:request UploadFileRequest

Met deze opdracht wordt een bestand gegenereerd met de naam UploadFileRequest in app/Http/Requests/UploadFileRequest. Open het stub en neem een ​​kijkje... Je zult het heel eenvoudig vinden, het bevat slechts twee methoden: autoriseren() en regels.

Het creëren van de validatielogica

Laten we de verzoekstub aanpassen aan de behoeften van onze applicatie. Wijzig het bestand zodat het er zo uitziet:

<?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'
       ];
   }
}

Er zijn niet veel veranderingen, maar merk op dat de methodeauthorize() nu true retourneert in plaats van false. Deze methode beslist of het verzoek al dan niet in de toepassing wordt toegelaten. Als deze is ingesteld op false, wordt voorkomen dat het verzoek het systeem binnenkomt (wat normaal gesproken een methode op de controller zou zijn). Dit zou een erg handige plek zijn om eventuele autorisatiecontroles op de gebruiker uit te voeren of enige andere logica die kan beslissen of het verzoek kan worden doorgestuurd naar de controller. Voorlopig keren we hier gewoon terug naar true om alles en nog wat toe te staan ​​het verzoek te gebruiken.

Bij de andere methode, Rules(), komt alle magie in het spel met betrekking tot validatie. Het idee is simpel: retourneer een array met een reeks regels in de vorm van:

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

Er zijn veel verschillende validatiebeperkingen die direct uit de doos door Laravel worden ondersteund. Voor een volledige lijst hiervan, bekijk de online documentatie hier. Voor onze uploadtoepassing zullen er twee velden zijn die via een POST-aanvraag van een formulier op de front-end worden doorgegeven. De parameter fileName moet in de body van het formulier worden opgenomen (d.w.z. vereist) en wordt gebruikt als de bestandsnaam waaronder we het bestand in de opslag opslaan (dit gebeurt in de controller - we komen er later op terug). We specificeren ook dat de bestandsnaam een ​​string moet zijn door een pipe-teken (|) en het woord 'string' toe te voegen. Beperkingen worden altijd begrensd door pipes, zodat u extra criteria voor het gegeven veld op één regel kunt opgeven! Wat een macht!

De tweede parameter, userFile , is het daadwerkelijke bestand dat de gebruiker uploadt vanuit een formulier op een webpagina. UserFile is ook vereist en Dan moet je een bestand zijn. Opmerking: Als we verwachtten dat het geüploade bestand een afbeelding zou zijn, dan zouden we in plaats daarvan de afbeeldingsbeperking gebruiken, waardoor de bestandstypen zouden worden beperkt die worden geaccepteerd als een van de populaire afbeeldingstypen (jpeg, png, bmp, gif of svg). Omdat we de gebruiker willen toestaan ​​elk type bestand te uploaden, houden we ons gewoon aan de bestandsvalidatiebeperking.

Dat is ongeveer alles wat het verzoekobject te bieden heeft. De belangrijkste taak ervan is om eenvoudigweg de aanvaardbare reeks criteria (beperkingen) vast te houden waaraan de lichaamsparameters van het formulier moeten voldoen om dieper in de toepassing te kunnen gaan. Iets anders om op te merken is dat deze twee velden (userFile en bestandsnaam) ook in de HTML-code moeten worden opgegeven in de vorm van invoervelden (waarbij de veldnaam overeenkomt met de naam in het verzoekobject).

U vraagt ​​zich misschien af: dit definieert zeker de kenmerken van wat een formulierverzoek moet bevatten, maar waar wordt de daadwerkelijke controle van deze beperkingen uitgevoerd? Wij zullen daar hierna op ingaan.

De regelaar aanpassen

Open app/Http/Controllers/UploadController en breng de volgende wijzigingen aan:

<?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
   }
}

Het is dus een vrij eenvoudige aanpak om de geüploade bestanden op schijf op te slaan. Hier is een overzicht van de upload()-methode hierboven:

  • Typ een hint voor de verzoekklasse in de controllermethode die de functionaliteit 'vlees en aardappelen' uitvoert, zodat we de binnenkomende gegevens automatisch kunnen valideren
  • Haal het bestand uit het (nu gevalideerde) verzoekobject in de controllermethode (in dit geval hebben we het upload() genoemd, maar het had ook een meer gestandaardiseerde naam kunnen hebben, zoals store()).
  • Haal de bestandsnaam uit het verzoek
  • Genereer de uiteindelijke bestandsnaam waaronder het bestand zal worden opgeslagen. De methode getClientOriginalExtension() pakt eenvoudigweg de oorspronkelijke extensie van het geüploade bestand.
  • Sla het bestand op in het lokale bestandssysteem met behulp van de storeAs()-methode, waarbij u het benoemde pad in de map /storage als eerste argument doorgeeft en de bestandsnaam waaronder u het wilt opslaan als tweede.
  • Retourneert een JSON-antwoord dat aangeeft dat het verzoek is geslaagd

Het bladsjabloon

Het laatste belangrijke stukje van deze puzzel is de blade template, die alle HTML, CSS en javascript voor onze eenvoudige applicatie zal bevatten. Hier is de code – we zullen het later uitleggen.

<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>

Dit is wat onze /uploaden pagina ziet er als volgt uit:

Het bladsjabloon

Dit is een heel typisch voorbeeld van een blade-bestand met een HTML-formulier en javascript/jQuery voor het toevoegen van asynchrone functionaliteit (zodat de pagina niet wordt vernieuwd). Er is een basis tag zonder method-attribuut (wat ik zo meteen zal uitleggen) en met een merkwaardig action-attribuut met de waarde {{route('file.upload')}}. In blade is dit wat bekend staat als een Richtlijn. Een directive is gewoon een mooie naam voor functie: het zijn functies die specifiek zijn voor blade-sjablonen en die verschillende bewerkingen uitvoeren die gebruikelijk zijn bij het maken van webpagina's en webapplicaties. Voor een beter begrip van alle coole dingen die blade kan doen, bekijk de docs hier. In het bovenstaande geval gebruiken we de routerichtlijn om een ​​URL te genereren voor onze formulierinzending.

Onthoud dat we onze routes eerder in de applicatie in het web.php-bestand hebben gedefinieerd, waarbij we voor elk ervan een gemakkelijk te onthouden naam hebben opgegeven. De richtlijn {{route()}} accepteert een naam van een route, zoekt deze op in de intern in de cache opgeslagen routeslijst en genereert een volledige URL op basis van de definitie van die route in het web.php-bestand. Voor dit eerste geval specificeren we dat we willen dat het formulier de ingediende gegevens naar de /process-URL van onze applicatie stuurt, die is gedefinieerd als een POST route.

Het volgende vreemde ding dat je misschien is opgevallen, is de @csrf-tag direct onder de openingsformuliertag. In blade genereert deze tag een _token-parameter op het formulier, die in de toepassing wordt gecontroleerd voordat de formuliergegevens mogen worden verwerkt. Dit zorgt ervoor dat de gegevens in het formulier een geldige oorsprong hebben en voorkomt cross-site-request-forgery-aanvallen. Voor meer informatie hierover, zie de docs.

Hierna definiëren we ons formulier als normaal, maar houd er rekening mee dat de namen van onze formulierparameters, userFile en fileName de exact dezelfde zoals gedefinieerd in ons verzoekobject. Als we vergeten een invoer op te nemen voor een bepaalde parameter die in het verzoekobject is gedefinieerd (of deze verkeerd hebben gespeld), mislukt het verzoek en wordt er een fout geretourneerd, waardoor wordt voorkomen dat het oorspronkelijke formulierverzoek ooit de controllermethode op UploadController@ raakt. proces .

Probeer het eens uit en dien via dit formulier een paar bestanden in bij de aanvraag. Navigeer daarna naar de /lijst pagina om de inhoud van de uploadmap te zien, met de bestanden die u hebt geüpload in een tabel:

Het bladsjabloon

The Bigger Picture

Laten we een stapje terug doen en kijken naar wat we hebben gedaan in deze Laravel-tutorial.

Dit diagram geeft de huidige stand van zaken van de applicatie weer (exclusief details op hoog niveau):

Laravel-tutorialdiagram

Houd er rekening mee dat het verzoekobject dat we aan het begin van deze Laravel-tutorial hebben gebouwd, dezelfde parameters moet hebben die zijn gedefinieerd in de regelsmethode als op het formulier in de blade-sjabloon (lees anders de sectie "De validatielogica maken") opnieuw. . De gebruiker voert het formulier in op een webpagina die wordt weergegeven via een blade-sjabloonengine (dit proces gebeurt uiteraard op de automatische piloot, dus we hoeven er niet eens over na te denken) en verzendt het formulier. De jQuery-code van de sjabloon onderaan stopt de standaardindiening (die automatisch naar een aparte pagina zou worden doorgestuurd), creëert een ajax-verzoek, laadt het verzoek met de formuliergegevens en uploadt het bestand, en stuurt het geheel naar de eerste laag van onze aanvraag: het verzoek.

Het verzoekobject wordt gevuld door de parameters binnen de methode Rules() te koppelen aan de ingediende formulierparameters, en valideert vervolgens de gegevens volgens elke opgegeven regel. Als aan alle regels is voldaan, wordt het verzoek doorgegeven aan de controllermethode die overeenkomt met de waarden die zijn gedefinieerd in het routebestand web.php. In dit geval is het de methode process() van de UploadController die het werk doet. Zodra we de controller raken, weten we al dat het verzoek is gevalideerd, dus we hoeven niet opnieuw te testen of de opgegeven bestandsnaam inderdaad een string is of dat de parameter userFile daadwerkelijk een bepaald type bestand bevat... We kunnen doorgaan als normaal.

De controllermethode haalt vervolgens de gevalideerde parameters uit het verzoekobject, genereert een volledige bestandsnaam door de doorgegeven parameter fileName samen te voegen met de oorspronkelijke extensie van userFile, slaat het bestand op in een map in onze applicatie en retourneert vervolgens een eenvoudige JSON-gecodeerde antwoord dat verifieert dat het verzoek succesvol was. Het antwoord wordt ontvangen door de jQuery-logica, die nog een paar UI-gerelateerde taken uitvoert, zoals het gedurende 5 seconden weergeven van het succesbericht (of foutbericht) en vervolgens verbergen ervan, en het wissen van de eerdere formulierinvoer... dit is zodat de gebruiker het weet zeker weten dat het verzoek succesvol is en kunnen desgewenst een ander bestand uploaden.

Let ook op het diagram hierboven waar de lijn tussen de client en de server wordt getrokken. Dit concept is absoluut cruciaal om te begrijpen en zal u helpen problemen en kwesties op te lossen die u in de toekomst kunt tegenkomen bij het jongleren met bijvoorbeeld meerdere asynchrone verzoeken die op elk willekeurig moment kunnen voorkomen. De scheiding bevindt zich precies op de grens van het verzoekobject. Het verzoekobject zelf kan worden beschouwd als de "gateway" naar de rest van de applicatie... Het doet de eerste validatie en registratie van formulierwaarden die worden doorgegeven vanuit de webbrowser. Als ze als geldig worden beschouwd, gaat het door naar de controller. Alles daarvoor bevindt zich aan de front-end (de "client" betekent letterlijk "op de computer van de gebruiker"). Het antwoord wordt vanuit de app teruggestuurd naar de clientzijde, waar onze jQuery-code geduldig luistert naar de aankomst ervan en een paar eenvoudige UI-taken uitvoert zodra het het ontvangt.

We hebben bijna 90+ belangrijke veelgestelde vragen behandeld Laravel- en PHP-gerelateerde interviewvragen voor zowel eerstejaars als ervaren kandidaten om de juiste baan te vinden.