PHP Formulieren
In PHP krijg je al snel te maken met formulieren. Een formulier is een manier om data invoer van gebruikers te verzamelen. Er zijn enorm veel verschillende formulieren en je bent er vast al heel wat tegengekomen. Bijvoorbeeld:
- Bestelformulier om producten te bestellen
- Registratieformulier om je te registeren op een website
- Loginformulier om je in te loggen op een website
- Je kunt je er vast nog veel meer bedenken...
Het maken van een formulier in HTML
Het formulier wat je hieronder ziet is een review formulier. Het formulier bestaat uit 3 invoer onderdelen:
- Naam
- Omschrijving
- Submit knop
html<form method="post"> <div class="mb-3"> <label for="inputName" class="form-label">Naam</label> <input type="text" name="name" class="form-control" id="inputName"> </div> <div class="mb-3"> <label for="inputDescription" class="form-label">Omschrijving</label> <input type="text" name="description" class="form-control" id="inputDescription"> </div> <button type="submit" name="submit" class="btn btn-primary">Verstuur</button> </form>
Het formulier wordt verzonden met de http method 'POST'. Er is geen action ingesteld op het formulier. Het formulier wordt zonder action verzonden naar zichzelf.
Het versturen van een formulier naar PHP
Bovenin je PHP bestand (boven je HTML) open je een nieuw PHP blok. In dit PHP blok zet je een if statement die kijkt of het formulier is verzonden.
phpif (isset($_POST['submit'])) { //hier komt code die de formulier elementen uitleest. }
Met behulp van de superglobal $_POST kun je kijken of de submit knop is ingedrukt. Het woord 'submit' dat tussen de vierkante haken staat [] komt overeen met name="submit" op het HTML formulier. De superglobal $_POST kun je gebruiken om formulier elementen op het name attribuut uit te lezen.
Uitlezen van formulier elementen met filter_input
Om formulier elementen uit te lezen in PHP kun je het beste de functie filter_input gebruiken omdat je hiermee kunt valideren en/of ongewenste karakters kan uitfilteren uit de verstuurde tekst. Hiermee houd je hackers en andere kwaadwillende gebruikers tegen voor wat betreft het invoeren van foutieve data.
Het onderstaande stukje code laat zien hoe je de naam en omschrijving kan uitlezen uit de geposte data vanuit het HTML formulier. De filter_input functie heeft 3 parameters:
- HTTP method (in dit geval
INPUT_POST). - Referentie naar
nameattribuut in het formulier. - Toegepaste filter methode (FILTER_SANITIZE_FULL_SPECIAL_CHARS filtert speciale karakters uit de tekst).
phpif (isset($_POST['submit'])) { $name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_FULL_SPECIAL_CHARS); $description = filter_input(INPUT_POST, 'description', FILTER_SANITIZE_FULL_SPECIAL_CHARS); }
Je kan vervolgens nog verdere checks doen op $name en $description. Bijvoorbeeld checken of het veld leeg is.
phpif (empty($name)) { //veld is leeg, toon validatie melding } else { //veld is gevuld }
Laten zien van validatie meldingen op je formulier en ingevoerde data vasthouden
Wanneer een gebruiker een formulier invult kan het soms zijn dat er een veld wordt overgeslagen of dat foutieve data wordt ingevuld. Dit kan per ongeluk zijn gegaan maar soms kan het ook een kwaadwillende gebruiker zijn die probeert het systeem te hacken. Wat de reden ook is maakt niet uit. Het is sowieso belangrijk om invoer data op te schonen, te valideren en feedback te geven aan de gebruiker wat er wel en niet goed is gegaan. Wanneer je de validatie melding op een formulier teruggeeft vindt de gebruiker het wel zo prettig dat zijn invoer wordt 'onthouden' en niet wordt gereset. Hieronder vind je code voorbeelden om dat voor elkaar te krijgen.
Om te beginnen willen we bepalen welke validatie meldingen we willen teruggeven aan de gebruiker. In het voorbeeld hieronder worden 2 constanten gedefinieerd met daarin de melding die de gebruiker gaat terugkrijgen.
phpconst NAME_REQUIRED = 'Naam is verplicht'; const DESCRIPTION_REQUIRED = 'Omschrijving is verplicht';
Daaronder definieer je 2 arrays. Eén array is voor het 'onthouden' van de inputs van de gebruiker. De andere array is voor het verzamelen van de errors (validatie meldingen) die je wilt teruggeven aan de gebruiker.
php$inputs = []; $errors = [];
Daaronder check je of de gebruiker de submit knop heeft ingedrukt en maak je gebruik van filter_input om de data te filteren. Ook worden de velden gecontroleerd of ze zijn ingevuld. Is het veld niet ingevuld? Dan wordt er een validatiemelding toegevoegd aan de $errors array. Is het veld wel ingevuld? Dan wordt de input van de gebruiker toegevoegd aan de $inputs array.
phpif (isset($_POST['submit'])) { //input wordt gefilterd $name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_FULL_SPECIAL_CHARS); $description = filter_input(INPUT_POST, 'description', FILTER_SANITIZE_FULL_SPECIAL_CHARS); if (empty($name)) { //NAME_REQUIRED validatie melding wordt toegevoegd aan de errors array $errors['name'] = NAME_REQUIRED; } else { //name input wordt toegevoegd aan de inputs array $inputs['name'] = $name; } if (empty($description)) { //DESCRIPTION_REQUIRED validatie melding wordt toegevoegd aan de errors array $errors['description'] = DESCRIPTION_REQUIRED; } else { //description input wordt toegevoegd aan de inputs array $inputs['description'] = $description; } if (count($errors) === 0) { //als er 0 elementen in de errors array zitten zijn er dus geen errors. //we kunnen hieronder de logica schrijven van het inserten van de data in een database tabel } }
Het HTML formulier zul je ook moeten aanpassen om de validatie meldingen te tonen en eerder ingevoerde data te tonen in het formulier. Hier wordt gebruik gemaakt van de null coalescing operator '??' om de code kort te houden.
php<form method="post"> <div class="mb-3"> <label for="inputName" class="form-label">Naam</label> <input type="text" name="name" class="form-control" id="inputName" value="<?= $inputs['name'] ?? '' ?>"> <div class="form-text text-danger"> <?= $errors['name'] ?? '' ?> </div> </div> <div class="mb-3"> <label for="inputDescription" class="form-label">Omschrijving</label> <input type="text" name="description" class="form-control" id="inputDescription" value="<?= $inputs['description'] ?? '' ?>"> <div class="form-text text-danger"> <?= $errors['description'] ?? '' ?> </div> </div> <button type="submit" name="submit" class="btn btn-primary">Verstuur</button> </form>
Ten slotte wil je de data ook opslaan in een database tabel. In het voorbeeld hieronder wordt uitgegaan van een review tabel met daarin de velden id, name en description.
php//wanneer we dus geen errors hebben in de errors array if (count($errors) === 0) { $query = $pdo->prepare('INSERT INTO review(name, description) VALUES (:name, :description)'); $query->bindParam('name', $inputs['name']); $query->bindParam('description', $inputs['description']); $query->execute(); //stuur je gebruiker door naar een pagina naar keuze (bijvoorbeeld review.php) header('Location: review.php'); }
Nog één keer het complete plaatje.
phpconst NAME_REQUIRED = 'Naam is verplicht'; const DESCRIPTION_REQUIRED = 'Omschrijving is verplicht'; $inputs = []; $errors = []; if (isset($_POST['submit'])) { //input wordt gefilterd $name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_FULL_SPECIAL_CHARS); $description = filter_input(INPUT_POST, 'description', FILTER_SANITIZE_FULL_SPECIAL_CHARS); if (empty($name)) { //NAME_REQUIRED validatie melding wordt toegevoegd aan de errors array $errors['name'] = NAME_REQUIRED; } else { //name input wordt toegevoegd aan de inputs array $inputs['name'] = $name; } if (empty($description)) { //DESCRIPTION_REQUIRED validatie melding wordt toegevoegd aan de errors array $errors['description'] = DESCRIPTION_REQUIRED; } else { //description input wordt toegevoegd aan de inputs array $inputs['description'] = $description; } if (count($errors) === 0) { $query = $pdo->prepare('INSERT INTO review(name, description) VALUES (:name, :description)'); $query->bindParam('name', $inputs['name']); $query->bindParam('description', $inputs['description']); $query->execute(); //stuur je gebruiker door naar een pagina naar keuze (bijvoorbeeld review.php) header('Location: review.php'); } } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Review</title> <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css"> <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script> </head> <body> <header> </header> <main> <div class="container-fluid vh-100"> <div class="row"> <div class="col"> <h1>Plaats een review</h1> <form method="post"> <div class="mb-3"> <label for="inputName" class="form-label">Naam</label> <input type="text" name="name" class="form-control" id="inputName" value="<?= $inputs['name'] ?? '' ?>"> <div class="form-text text-danger"> <?= $errors['name'] ?? '' ?> </div> </div> <div class="mb-3"> <label for="inputDescription" class="form-label">Omschrijving</label> <input type="text" name="description" class="form-control" id="inputDescription" value="<?= $inputs['description'] ?? '' ?>"> <div class="form-text text-danger"> <?= $errors['description'] ?? '' ?> </div> </div> <button type="submit" name="submit" class="btn btn-primary">Verstuur</button> </form> </div> </div> </div> </main> <footer> </footer> </body> </html>