PHP Β· Les 7
Formulieren verwerken
$_GET, $_POST, htmlspecialchars, filter_var validatie en header redirect Β· 30 min
$_GET en $_POST β superglobals
PHP heeft ingebouwde superglobale arrays die formulierdata ontvangen. Ze zijn overal beschikbaar, ook in functies.
$_GET
- β Data in de URL:
?naam=Jan - β Zichtbaar in de adresbalk
- β Geschikt voor zoeken, filteren, paginering
- β Max. ~2000 tekens
- β Nooit voor wachtwoorden!
$_POST
- β Data in de request body
- β Niet zichtbaar in adresbalk
- β Geschikt voor formulieren, inloggen
- β Geen limiet op grootte
- β Gebruik voor gevoelige data
<?php
// URL: /zoek?term=php&pagina=2
$zoekterm = $_GET["term"] ?? ""; // "php"
$pagina = $_GET["pagina"] ?? 1; // "2" (string!)
$pagina = (int) $pagina; // Cast naar int: 2
// POST data na formulier submit
$naam = $_POST["naam"] ?? "";
$email = $_POST["email"] ?? "";
// $_SERVER β info over het verzoek
$methode = $_SERVER["REQUEST_METHOD"]; // "GET" of "POST"
$url = $_SERVER["REQUEST_URI"]; // "/contact?ref=home"
// Formulier detect
if ($_SERVER["REQUEST_METHOD"] === "POST") {
// verwerk formulier
} else {
// toon formulier
}
β οΈ Let op verschil met JS
In JS lees je URL-parameters via new URLSearchParams(location.search). In PHP is $_GET automatisch beschikbaar. JS heeft geen directe toegang tot POST-data zonder fetch/XMLHttpRequest β dat doet PHP op de server.
htmlspecialchars β XSS voorkomen
Nooit gebruikersinvoer direct in HTML plaatsen. Een aanvaller kan anders JavaScript injecteren (XSS β Cross-Site Scripting).
β FOUT β kwetsbaar voor XSS
// Gebruiker voert in: <script>alert('gehackt!')</script>
echo "Hallo " . $_POST["naam"]; // Script wordt uitgevoerd!
β CORRECT β veilig
<?php $naam = htmlspecialchars($_POST["naam"] ?? "", ENT_QUOTES, "UTF-8"); echo "Hallo " . $naam; // <script> wordt omgezet naar <script> β onschadelijk
<?php
// htmlspecialchars zet gevaarlijke tekens om:
// & β &
// < β <
// > β >
// " β " (bij ENT_QUOTES ook ' β ')
// Standaard helper-functie die je kunt hergebruiken
function esc(string $waarde): string {
return htmlspecialchars($waarde, ENT_QUOTES | ENT_HTML5, "UTF-8");
}
$invoer = '<script>alert("xss")</script>';
echo esc($invoer);
// Toont letterlijk de tekst, geen script
π Komt terug in Symfony
In Symfony's Twig-templates is automatische escaping ingeschakeld. {{ gebruiker.naam }} roept automatisch htmlspecialchars() aan. Alleen {{ tekst|raw }} slaat escaping over β gebruik dat zorgvuldig.
Validatie met filter_var
<?php
$fouten = [];
// Naam valideren
$naam = trim($_POST["naam"] ?? "");
if (empty($naam)) {
$fouten[] = "Naam is verplicht.";
} elseif (strlen($naam) < 2) {
$fouten[] = "Naam moet minimaal 2 tekens bevatten.";
} elseif (strlen($naam) > 100) {
$fouten[] = "Naam mag maximaal 100 tekens bevatten.";
}
// E-mail valideren
$email = trim($_POST["email"] ?? "");
if (empty($email)) {
$fouten[] = "E-mail is verplicht.";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$fouten[] = "Ongeldig e-mailadres.";
}
// URL valideren
$website = trim($_POST["website"] ?? "");
if (!empty($website) && !filter_var($website, FILTER_VALIDATE_URL)) {
$fouten[] = "Ongeldige URL.";
}
// Integer valideren
$leeftijd = filter_var($_POST["leeftijd"] ?? "", FILTER_VALIDATE_INT);
if ($leeftijd === false || $leeftijd < 0 || $leeftijd > 150) {
$fouten[] = "Ongeldige leeftijd.";
}
// Sanitizen (schoonmaken, niet valideren)
$naam = filter_var($naam, FILTER_SANITIZE_SPECIAL_CHARS);
$integer = filter_var("42abc", FILTER_SANITIZE_NUMBER_INT); // "42"
if (empty($fouten)) {
echo "Formulier verwerkt!\n";
} else {
foreach ($fouten as $fout) {
echo "β $fout\n";
}
}
π Komt terug in Symfony
Symfony's Validator component doet dit veel eleganter: #[Assert\NotBlank], #[Assert\Email], #[Assert\Length(min: 2, max: 100)] boven entity-properties. Geen handmatige if-checks meer nodig.
HTML-formulier bouwen
Het HTML-formulier stuurt data naar het PHP-script via method="POST" en action="".
<!-- contact.html (of PHP-bestand met HTML) -->
<form method="POST" action="/contact">
<!-- Tekstveld -->
<label for="naam">Naam:</label>
<input type="text" id="naam" name="naam"
value="<?= htmlspecialchars($oud['naam'] ?? '') ?>"
required>
<!-- E-mailveld -->
<label for="email">E-mail:</label>
<input type="email" id="email" name="email"
value="<?= htmlspecialchars($oud['email'] ?? '') ?>"
required>
<!-- Selectbox -->
<label for="onderwerp">Onderwerp:</label>
<select id="onderwerp" name="onderwerp">
<option value="algemeen">Algemeen</option>
<option value="technisch">Technisch</option>
<option value="factuur">Factuur</option>
</select>
<!-- Tekstgebied -->
<label for="bericht">Bericht:</label>
<textarea id="bericht" name="bericht" rows="5">
<?= htmlspecialchars($oud['bericht'] ?? '') ?>
</textarea>
<!-- Submit -->
<button type="submit">Verstuur</button>
</form>
Slimme truc: waarden bewaren na fout
Door value="<?= htmlspecialchars($oud['naam'] ?? '') ?>" te gebruiken, blijft de ingevulde waarde staan na een validatiefout. De gebruiker hoeft niet alles opnieuw in te typen.
Compleet verwerkingsscript + redirect
<?php
// contact.php β verwerkt GET (toon) en POST (verwerk)
$fouten = [];
$oud = [];
$succes = false;
if ($_SERVER["REQUEST_METHOD"] === "POST") {
// Lees en schoon invoer
$naam = trim($_POST["naam"] ?? "");
$email = trim($_POST["email"] ?? "");
$bericht = trim($_POST["bericht"] ?? "");
// Sla op voor terugplaatsen bij fout
$oud = compact("naam", "email", "bericht");
// Valideer
if (empty($naam)) $fouten[] = "Naam is verplicht.";
if (empty($email)) $fouten[] = "E-mail is verplicht.";
elseif (!filter_var($email, FILTER_VALIDATE_EMAIL))
$fouten[] = "Ongeldig e-mailadres.";
if (strlen($bericht) < 10)
$fouten[] = "Bericht te kort (min. 10 tekens).";
if (empty($fouten)) {
// β
Verwerk: opslaan in DB, e-mail sturen, etc.
// mail($email, "Bevestiging", "Ontvangen: $bericht");
// PRG-patroon: redirect na succesvolle POST
// Voorkomt dat de gebruiker bij refresh opnieuw submits
header("Location: /bedankt");
exit; // ALTIJD exit na header redirect!
}
}
?>
<!-- HTML-formulier (vereenvoudigd) -->
<?php foreach ($fouten as $f): ?>
<p style="color:red"><?= htmlspecialchars($f) ?></p>
<?php endforeach; ?>
<form method="POST">
<input name="naam" value="<?= htmlspecialchars($oud['naam'] ?? '') ?>">
<input name="email" value="<?= htmlspecialchars($oud['email'] ?? '') ?>">
<textarea name="bericht"><?= htmlspecialchars($oud['bericht'] ?? '') ?></textarea>
<button>Verstuur</button>
</form>
PRG-patroon β Post/Redirect/Get
Na een succesvolle POST altijd redirecten. Zo voorkomt je dat de browser bij vernieuwen het formulier opnieuw instuurt ("Wilt u dit formulier opnieuw versturen?").
π Komt terug in Symfony
In Symfony doe je exact hetzelfde maar eleganter: $form->handleRequest($request), if ($form->isSubmitted() && $form->isValid()), dan return $this->redirectToRoute('success'). Symfony's Forms + Validator doen de validatie; jij schrijft alleen de logica.
Sandbox β formulierverwerking simuleren
In de sandbox simuleren we POST-data via een PHP-array, omdat PHP-WASM geen echte HTTP-requests verwerkt.
// output
Klik op Uitvoeren...
Kennischeck
Les 7 afronden
Ga door naar klassen en namespaces β de laatste les β