Formulier

Inleiding

In deze paragraaf zal stap voor stap besproken worden hoe je een afbeelding kan uploaden naar de server en dit kan opslaan in de database. Hiervoor gebruiken we de case: de functionaliteit om een profielfoto toe te voegen aan een user account.

Formulier

Maak een view waarin je het upload formulier kan plaatsen. Bv profiel.view.php

In profiel.view.php komt het formulier te staan.

In het formulier :

<?php
view("parts/header", ['title' => 'about']);
view("parts/navigatie-menu");
?>


<form action="/profielfoto" method="post" enctype="multipart/form-data">
    Selecteer een profielfoto:
    <input type="file" name="foto" id="foto">
    <!-- om eventuele errors te tonen -->
    <?php if (isset($errors['foto])): ?>
      <p class="text-red-500 text-sm my-2"><?= $errors['foto'] ?></p>
    <?php endif; ?>

    <input type="submit" value="Upload profielfoto" name="submit">
</form>
<?php
view("parts/footer");

Belangrijk is dat je aan je form enctype="multipart/form-data" toevoegd. Dit maakt het mogelijk om bestanden te versturen.
Daarna kan je eenvoudig de <input type="file" .. gebruiken als veld waar je de afbeelding kan selecteren.

Router

Als action hebben we /profielfoto dus daar moeten we een route voor aanmaken

$route->post('profielfoto','controllers/profielfoto-store');

Controller

We maken een controller: profielfoto-store.php

In dit bestand gaan we de foto toevoegen. We gaan daarbij de foto in een map plaatsen en in de database slaan we het pad op waar de foto opgeslagen is. Omdat afbeeldingen veel ruimte innemen is dit de meest praktische manier van opslaan.

De bestanden die worden geupload zijn terug te vinden in de variabele $_FILE. De naam van de profielfoto kan je met $_FILE['foto']['name'] vinden.

Belangrijk is dat je een controle doet of het een afbeelding betreft. Anders zou het ook een gevaarlijk virus kunnen zijn.
Indien het een afbeelding is mag deze opgeslagen worden in de afbeeldingen map. Daarna wil je het pad naar de afbeelding toevoegen in de database. Zodat je weet bij welke gebruiker de afbeelding hoort. Vaak is het handig om de naam van de afbeelding aan te passen naar een hash, zodat het bijna onmogelijk is om dubbele namen te krijgen.

Met wat zoeken op internet is deze code snel te vinden. Eventueel kan je hier ook heel goed een AI bot voor gebruiken.

Hieronder een voorbeeldje. Let op de code is niet getest.

$uploadDirectory = 'images/'; // map waarin de afbeeldingen worden opgeslagen

if (isset($_FILES["foto"])) { //wordt er een afbeelding verstuurd, dan ...
    
    $errors = []; //hier gaan we fouten in opslaan

    //de file extensie ophalen
    $imageFileType = strtolower(pathinfo($uploadFile,PATHINFO_EXTENSION));
    
    // Controleer of het bestand een afbeelding is
    if(getimagesize($_FILES["afbeelding"]["tmp_name"])) {
        $errors['foto'] = "Bestand is geen afbeelding.";
    }

    // Controleer de bestandsgrootte
    if ($_FILES["afbeelding"]["size"] > 5000000) {
        $errors['foto'] = "Sorry, het bestand is te groot.";
    }

    // Toegestane bestandstypen
    $allowedExtensions = array("jpg", "jpeg", "png", "gif");
    if (!in_array($imageFileType, $allowedExtensions)) {
        $errors['foto'] = "Sorry, alleen JPG, JPEG, PNG en GIF bestanden zijn toegestaan.";
    }

    if(!empty($error)){ //fouten dus stoppen en terugsturen naar formlier
       view('profielfoto',['errors'=>$errors]);
    } else {
       //uploadFile is de naam zoals wij de afbeelding uiteindelijk gaan opslaan
       $uploadFile = $uploadDirectory . hash(date().random_int(1,1000000)).".".$imageFileType;
       move_uploaded_file($_FILES["foto"]["tmp_name"], $uploadFile);

       //de afbeelding is nu opgeslagen, nu gaan we deze ook in de database opslaan bij de gebruiker
       $db = new Database();
       $db->query("UPDATE users set profielfoto=? where id=?",[
         $uploadFile,
         user()->id,  // de op dat moment ingelogde gebruiker
       ];
       //PAS AAN: stuur de gebruiker naar de gewenste pagina
       view('....');
    }
    die();
}

view('profielfoto',['errors'=>['foto'=>'Geen foto meegestuurd']);