Formulieren

Inleiding

In deze tutorial leer je hoe je formulieren kunt maken op een technisch correcte wijze. In een aantal stappen neem ik je mee van een heel eenvoudig formulier tot meer complexe zaken.

Request Methods

Voordat je begint met het maken van formulieren moet je iets weten over request methods. Als je een URL intypt in je browser (en op enter drukt) of als je op een link klikt dan zal je webbrowser een verzoek sturen naar de webserver welke op zijn beurt weer een antwoord terug stuurt. Dat sturen van een verzoek noemen we in de IT een request. Het antwoord van de server noemen we een response.

Request en Response

Bij het verzenden van het request kan de browser enige informatie meesturen. Een onderdeel van deze informatie is de request method. Er zijn meerdere request methodes maar ik beperk me hier tot de twee meest gebruikte. Ga je later formulieren schrijven waarin je ook data uit de database kunt wijzigen of verwijderen dan moet je je nog eens in de andere request methodes verdiepen.

1. De GET methode

De GET methode is de meest gebruikte methode. Als je een URL opvraagt of op een link klikt dan zal de browser dit verzoek aanvragen in de GET methode. Ook formulier data kan verstuurd worden in de GET methode. Dit betekent wel dat er data in de URL komt te staan. Dat kan er dan ongeveer zo uitzien:

http://mysite.nl/contact.php?naam=Frank+Beentjes&email=frankbeen%40gmail.com&bericht=Dit+is+een+bericht
2. De POST methode

De POST methode wordt vaak gebruikt voor het verzenden van formulierdata. In tegenstelling tot de GET methoed wordt de data niet in de URL geplaatst maar komt de data in de request body te staan. Dit vinden de meeste programmeurs een fraaiere oplossing omdat de gebruiker de ruwe data dan niet ziet. Bovendien kunnen we nu aan de hand van de request methode bepalen of we formulierdata kunnen verwachten of niet. De schrijfwijze is exact hetzelfde als in de URL na het vraagteken:

naam=Frank+Beentjes&email=frankbeen%40gmail.com&bericht=Dit+is+een+bericht

Een simpel formulier

Om een formulier te kunnen maken kunnen we eerst de HTML schrijven.
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Mijn eerste formulier</title>
    </head>
    <body>
        <form method="post">
            <input type="text" name="naam" value="">
            <input type="email" name="email" value="">
            <button type="submit">Verzenden</button>
        </form>
    </body>
</html>

Het voorbeeld laat een HTML5 formulier zien. Sommigen van jullie zullen het action attribuut missen in het <form> element. In HTML5 mag deze weggelaten worden. Sterker nog -als het action attribuut opgegeven wordt- dan mag deze niet leeg zijn. Laat je het action attribuut achterwege dan zal het formulier naar de URL van de huidige pagina gestuurd worden. Binnen het formulier vinden we twee formuliervelden en een "verzend" knop. Voor het email veld gebruiken we ook type email zodat de browsers het ingevoerde mailadres al kunnen valideren. HTML5 kent meer types dan zijn voorgangers. Belangrijk zijn de name attributen. Dit zijn de identifiers waarmee we de waarden weer terug kunnen vinden binnen PHP wanneer het formulier verstuurt is.

Client-side validatie is makkelijk te omzeilen. Verzuim dus nooit om in php (server-side) te valideren. De gebruiker heeft geen invloed op server-side validatie en bovendien is server-side validatie onafhankelijk van de software op de client.

De minimale PHP code

Nu we de HTML klaar hebben wordt het tijd om de PHP code te schrijven. De pagina kan op twee manieren aangeroepen worden: In de GET methode wanneer het formulier nog niet verstuurd is. We zullen dan met name het formulier laten zien zodat de gebruiker deze kan gaan invullen. De tweede manier is de POST methode. Als we weten dat het formulier verstuurd is dan kunnen we de ingevulde gegevens gaan valideren en als de validatie slaagt dan kunnen we een of meerdere akties uitvoeren zoals het verzenden van een email of het opslaan van de ingevulde gegevens in de database.

<?php

// functie die de formuliervelden valideert en foutmeldingen aanmaakt
function validate($naam, $email)
{
    $errors = array();
    
    // hier komt de daadwerkelijke validatie 
    
    // geef de array met foutmeldingen terug
    return $errors;
}

// indien het formulier verstuurd is
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
    // valideer de ingevulde gegevens
    $errors = validate($_POST['naam'], $_POST['email']);
    
    // als er geen fouten voortkomen uit de validatie
    if(!count($errors))
    {
        /* 
         * Verwerk hier je formulier, bijvoorbeeld een email versturen of
         * de gegevens opslaan in de database
         */
                
        // redirect de gebruiker 
        header('Location: confirmation.html');
        exit;
    }
}
?>

In het voorbeeld hierboven zie je eigenlijk alleen maar dat wat je minimaal nodig zult hebben om een formulier op de juiste wijze af te handelen. Als eerste testen we of de pagina in de POST methode aangevraagd is. Als dat zo is dan mogen we aannemen dat iemand op de verzend knop geklikt heeft en dat de items $_POST['naam'] en $_POST['email'] aangemaakt zijn en een waarde hebben. Vervolgens zullen we de waardes willen testen. Invoer van buitenaf is altijd vuil. Je kunt jezelf de volgende vragen stellen:

  • Is er een naam ingevuld?
  • Is het verplicht om een naam in te vullen?
  • Is er een mailadres ingevuld?
  • Is het verplicht om een mailadres in te vullen?
  • Is het een geldig mailadres?

Met een eigen geschreven validatie functie zullen we de invoer dus gaan controlleren. Als er geen validatie fouten zijn dan kunnen we het formulier gaan verwerken. Wat er precies moet gaan gebeuren is helemaal afhankelijk van waarvoor het formulier bedoeld is. Gaat het om een contactformulier dan willen we waarschijnlijk een mail sturen naar de eigenaar van de website. Maar de mogelijkheden zijn enorm.

Redirect

Nadat het formulier verwerkt is moeten we nog een belangrijk ding doen. De gebuiker doorsturen of redirecten. Dit doen we om te voorkomen dat formulieren meerdere keren ingediend gaan worden. Je mag de gebruiker naar exact dezelfde pagina doorsturen als je hem maar doorstuurt zodat er geen pagina -die in de POST methode is aangeroepen en verwerkt is- opnieuw gaat opbouwen. De gebruiker kan natuurlijk ook doorgestuurd worden naar een andere pagina alwaar hij een bevestiging krijgt dat het formulier succesvol verwerkt is. Het redirecten kun je doen met behulp van de header functie. Deze functie schrijft een regel in de http header. Belangrijk detail van deze functie is dat je hem alleen mag gebruiken voordat de http header verstuurt is. En aangezien deze verstuurd wordt voor de eerste output mag je script absoluut nog geen enkele output verzonden hebben. Onder output verstaan we HTML, CSS, tekst, javascript, foutmeldingen en zelfs een enkel karakter zoals een spatie of een carriage return. Vergeet niet na een redirect ook het script te beeindigen met een exit; anders loopt het script gewoon door.

Validatie

Omdat mensen de gekste dingen doen moeten we alle input die mensen mogen maken zien als "zwaar vervuild" en "onveilig". Bovendien willen we minimaal dat een aantal velden wel ingevuld zijn en niet leeg gelaten worden. Of een veld leeg is of niet kan simpel met de functie strlen gecontroleerd worden. Of een string een geldig mailadres is of niet kunnen we het beste controleren met de functie filter_var. Indien de de validatie mislukt maken we een foutmelding aan. Hieronder zie je de complete validatie functie.

function validate($naam, $email)
{
    $errors = array();
    
    // validatieregels voor de naam
    if(strlen($naam) < 2)
        $errors['naam'] = 'U heeft geen naam ingevuld.';
    
    // validatieregels voor het mailadres
    if(!strlen($email))
        $errors['email'] = 'U heeft geen email adres ingevuld.';
    else if(!filter_var($email, FILTER_VALIDATE_EMAIL))
        $errors['email'] = 'U heeft een ongeldig email adres ingevuld.';
    
    // geef de array met foutmeldingen terug
    return $errors;
}

Leuk dat we foutmeldingen hebben maar die willen we ook weergeven. Dit kan met een simpele foreach lus boven het formulier weergegeven worden.

if(count($errors)) {
    echo '<ul id="errors">';
    foreach($errors as $error) {
        echo '<li>' . $error . '</li>';
    }
    echo '</ul>';
}

Nu ontstaat er wel een klein probleempje. In de eerste regel op bovenstaand stukje code gaan we er van uit dat de variabele $errors reeds bestaat. Dit is echter niet altijd het geval. Als de pagina namelijk in de GET methode aangeroepen wordt zal de code binnen het if statement niet uitgevoerd worden en zal $errors niet bestaan. Dit kunnen we op een nette manier oplossen door $errors vóór het if statement te initialiseren:

// initialisatie
$errors = array();

Werkend voorbeeld

Hieronder staat een werkend voorbeeld met alles inbegrepen wat we tot nu toe behandeld hebben. Het enigste is dat er na het invullen en valideren verder nog niets gebeurd met de ingevulde gegevens maar dat stukje laat ik geheel aan jou zelf over.

<?php

// functie die de formuliervelden valideert en foutmeldingen aanmaakt
function validate($naam, $email)
{
    $errors = array();
    
    // validatieregels voor de naam
    if(strlen($naam) < 2)
        $errors['naam'] = 'U heeft geen naam ingevuld.';
    
    // validatieregels voor het mailadres
    if(!strlen($email))
        $errors['email'] = 'U heeft geen email adres ingevuld.';
    else if(!filter_var($email, FILTER_VALIDATE_EMAIL))
        $errors['email'] = 'U heeft een ongeldig email adres ingevuld.';
    
    // geef de array met foutmeldingen terug
    return $errors;
}

// initialisatie
$errors = array();

// indien het formulier verstuurd is
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
    // valideer de ingevulde gegevens
    $errors = validate($_POST['naam'], $_POST['email']);
    
    // als er geen fouten voortkomen uit de validatie
    if(!count($errors))
    {
        /* 
         * Verwerk hier je formulier, bijvoorbeeld een email versturen of
         * de gegevens opslaan in de database
         */
        
        // redirect de gebruiker 
        header('Location: confirmation.html');
        exit;
    }
}
?>
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Mijn eerste formulier</title>
    </head>
    <body>
        <?php
            if(count($errors)) {
                echo '<ul id="errors">';
                foreach($errors as $error) {
                    echo '<li>' . $error . '</li>';
                }
                echo '</ul>';
            }
        ?>
        <form method="post">
            <input type="text" name="naam" value="">
            <input type="email" name="email" value="">
            <button type="submit">Verzenden</button>
        </form>
    </body>
</html>

Formuliervelden invullen

Als je nu het formulier in de praktijk zou gebruiken en een validatie foutmelding krijgt nadat je het formulier verstuurt hebt dan kom je misschien tot de onaangename ontdekking dat alle formuliervelden weer leeg zijn. Dit is niet gebruiksvriendelijk en dus moeten we dat anders doen. We kunnen de formuliervelden van een waarde voorzien door het value attribuut in te vullen.

<input type="text" name="naam" value="<?php echo $naam; ?>">
<input type="email" name="email" value="<?php echo $email; ?>">

Net als bij de $errors variabele moeten we dan wel zorgen dat we $naam en $email initialiseren en na het indienen van de gegevens ook de waarde krijgen uit de $_POST array:

// initialisatie
$naam = '';
$email = '';
$errors = array();

// indien het formulier verstuurd is
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
    // overschrijf de variabelen met de waarde uit de $_POST array
    $naam = $_POST['naam'];
    $email = $_POST['email'];
    
    // ...
}
Gebruik nooit rechtstreeks de $_POST elementen in de HTML omdat deze elementen niet zullen bestaan wanneer de pagina in de GET methode aangeroepen wordt!

Eindresultaat

Het nieuwe formulier met ingevulde formuliervelden na een mislukte validatie:

<?php

// functie die de formuliervelden valideert en foutmeldingen aanmaakt
function validate($naam, $email)
{
    $errors = array();
    
    // validatieregels voor de naam
    if(strlen($naam) < 2)
        $errors['naam'] = 'U heeft geen naam ingevuld.';
    
    // validatieregels voor het mailadres
    if(!strlen($email))
        $errors['email'] = 'U heeft geen email adres ingevuld.';
    else if(!filter_var($email, FILTER_VALIDATE_EMAIL))
        $errors['email'] = 'U heeft een ongeldig email adres ingevuld.';
    
    // geef de array met foutmeldingen terug
    return $errors;
}

// initialisatie
$naam = '';
$email = '';
$errors = array();

// indien het formulier verstuurd is
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
    // overschrijf de variabelen met de waarde uit de $_POST array
    $naam = $_POST['naam'];
    $email = $_POST['email'];

    // valideer de ingevulde gegevens
    $errors = validate($_POST['naam'], $_POST['email']);
    
    // als er geen fouten voortkomen uit de validatie
    if(!count($errors))
    {
        /* 
         * Verwerk hier je formulier, bijvoorbeeld een email versturen of
         * de gegevens opslaan in de database
         */
        
        // redirect de gebruiker 
        header('Location: confirmation.html');
        exit;
    }
}
?>
<!doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Mijn eerste formulier</title>
    </head>
    <body>
        <?php
            if(count($errors)) {
                echo '<ul id="errors">';
                foreach($errors as $error) {
                    echo '<li>' . $error . '</li>';
                }
                echo '</ul>';
            }
        ?>
        <form method="post">
            <input type="text" name="naam" value="<?php echo $naam ?>">
            <input type="email" name="email" value="<?php echo $email ?>">
            <button type="submit">Verzenden</button>
        </form>
    </body>
</html>

Reacties

Om een reactie te plaatsen kun je jezelf eenmalig registeren of je kunt hier inloggen.