Appearance
Kapitel 9: Formulare und Benutzerinteraktion
9.1 Unterschied zwischen GET und POST
GET-Methode
php
<!-- formular_get.html -->
<!DOCTYPE html>
<html>
<head>
<title>GET-Formular</title>
</head>
<body>
<form method="get" action="verarbeite_get.php">
<label>Name: <input type="text" name="name"></label><br>
<label>Alter: <input type="number" name="alter"></label><br>
<button type="submit">Senden</button>
</form>
</body>
</html>
<?php
// verarbeite_get.php
// GET-Daten werden über URL übertragen
$name = $_GET['name'] ?? 'Unbekannt';
$alter = $_GET['alter'] ?? 0;
echo "Name: " . $name . "<br>";
echo "Alter: " . $alter . "<br>";
// URL sieht so aus: verarbeite_get.php?name=Max&alter=25
?>
<!--
Vorteile von GET:
+ Daten sind in URL sichtbar (kann bookmarkt werden)
+ Einfach zu debuggen
+ Für Suchen, Filterung geeignet
Nachteile von GET:
- Daten in URL sichtbar (unsicher für Passwörter!)
- URL-Längenbegrenzung (ca. 2000 Zeichen)
- Nicht für grosse Datenmengen
-->POST-Methode
php
<!-- formular_post.html -->
<form method="post" action="verarbeite_post.php">
<label>Benutzername: <input type="text" name="benutzer"></label><br>
<label>Passwort: <input type="password" name="passwort"></label><br>
<button type="submit">Login</button>
</form>
<?php
// verarbeite_post.php
// POST-Daten werden im HTTP-Body übertragen
$benutzer = $_POST['benutzer'] ?? '';
$passwort = $_POST['passwort'] ?? '';
echo "Benutzername: " . $benutzer . "<br>";
// Passwort sollte NIEMALS ausgegeben werden!
// In URL sieht man nichts: verarbeite_post.php
?>
<!--
Vorteile von POST:
+ Daten nicht in URL sichtbar (sicherer)
+ Keine URL-Längenbegrenzung
+ Für Login, Registrierung, grosse Daten geeignet
Nachteile von POST:
- Kann nicht bookmarkt werden
- Schwieriger zu debuggen
-->Unterschied: GET vs. POST (Tabelle)
| Merkmal | GET | POST |
|---|---|---|
| Datenübertragung | URL-Parametern | HTTP-Body (versteckt) |
| Sicherheit | Niedrig (sichtbar in URL) | Höher (nicht in URL) |
| Datenmenge | Begrenzt (URL-Länge) | Unbegrenzt |
| Bookmarkbar | Ja | Nein |
| Cachebar | Ja | Nein |
| Anwendung | Suche, Filterung | Login, Registrierung, Upload |
| Idempotenz | Idempotent (mehrmals ausführbar) | Nicht idempotent |
Empfehlung:
- GET: Für Datenabfrage (Suche, Filterung)
- POST: Für Dateneingabe (Login, Registrierung, Upload)
9.2 Formular mit method="get" / "post"
Formular-Erstellung (HTML)
html
<!-- formular.html -->
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Kontaktformular</title>
</head>
<body>
<h2>Kontaktformular</h2>
<form method="post" action="verarbeite.php">
<label>Name:<br>
<input type="text" name="name" required>
</label><br><br>
<label>E-Mail:<br>
<input type="email" name="email" required>
</label><br><br>
<label>Nachricht:<br>
<textarea name="nachricht" rows="5" cols="30" required></textarea>
</label><br><br>
<label>Geschlecht:<br>
<input type="radio" name="geschlecht" value="m"> Männlich
<input type="radio" name="geschlecht" value="w"> Weiblich
<input type="radio" name="geschlecht" value="d"> Divers
</label><br><br>
<label>Interessen:<br>
<input type="checkbox" name="interessen[]" value="sport"> Sport
<input type="checkbox" name="interessen[]" value="musik"> Musik
<input type="checkbox" name="interessen[]" value="lesen"> Lesen
</label><br><br>
<label>Land:<br>
<select name="land">
<option value="de">Deutschland</option>
<option value="at">Österreich</option>
<option value="ch">Schweiz</option>
</select>
</label><br><br>
<button type="submit">Senden</button>
<button type="reset">Zurückseten</button>
</form>
</body>
</html>Formulardaten verarbeiten (PHP)
php
<?php
// verarbeite.php
header('Content-Type: text/html; charset=utf-8');
// POST-Daten empfangen
$name = $_POST['name'] ?? 'Unbekannt';
$email = $_POST['email'] ?? '';
$nachricht = $_POST['nachricht'] ?? '';
$geschlecht = $_POST['geschlecht'] ?? '';
$interessen = $_POST['interessen'] ?? []; // Array!
$land = $_POST['land'] ?? '';
// Ausgabe
echo "<h2>Vielen Dank für Ihre Nachricht!</h2>";
echo "Name: " . htmlspecialchars($name) . "<br>";
echo "E-Mail: " . htmlspecialchars($email) . "<br>";
echo "Nachricht: " . nl2br(htmlspecialchars($nachricht)) . "<br>";
echo "Geschlecht: " . htmlspecialchars($geschlecht) . "<br>";
// Array ausgeben (Interessen)
if (!empty($interessen)) {
echo "Interessen: " . implode(", ", $interessen) . "<br>";
}
echo "Land: " . htmlspecialchars($land) . "<br>";
// Weiterleitung (nach 3 Sekunden)
header("refresh:3;url=formular.html");
echo "<p>Sie werden in 3 Sekunden weitergeleitet...</p>";
?>9.3 $_GET / $_POST / $_REQUEST Daten empfangen
Superglobals in PHP
php
<?php
// $_GET: Daten aus URL-Parametern (methode="get")
// URL: verarbeite.php?name=Max&alter=25
$name = $_GET['name'] ?? '';
$alter = $_GET['alter'] ?? 0;
// $_POST: Daten aus Formular (methode="post")
$benutzer = $_POST['benutzer'] ?? '';
$passwort = $_POST['passwort'] ?? '';
// $_REQUEST: Enthält Daten aus GET, POST und COOKIE
$daten = $_REQUEST['daten'] ?? '';
// Achtung: $_REQUEST ist unsicher (man weiss nicht, woher Daten kommen)
// Empfehlung: Immer spezifisch sein ($_GET oder $_POST)
?>
<!--
Unterschied:
- $_GET: Nur GET-Daten
- $_POST: Nur POST-Daten
- $_REQUEST: GET + POST + COOKIE (Reihenfolge in php.ini: variables_order)
-->Sichere Datenverarbeitung
php
<?php
// Schlechte Praxis (unsicher)
$name = $_GET['name']; // FEHLER! Wenn 'name' nicht existiert
echo $name;
// Gute Praxis (mit Standardwert)
$name = $_GET['name'] ?? 'Gast'; // Null-Koaleszenz-Operator
echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
// Noch besser: prüfen, ob gesetzt
if (isset($_GET['name'])) {
$name = $_GET['name'];
} else {
$name = 'Gast';
}
// Oder: filter_input() verwenden (empfohlen!)
$name = filter_input(INPUT_GET, 'name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
if ($name === null || $name === false) {
$name = 'Gast';
}
echo $name;
?>9.4 Formularvalidierung (nicht leer, Format, Länge)
Clientseitige Validierung (HTML/JavaScript)
html
<!-- formular_validierung.html -->
<form method="post" action="verarbeite.php" onsubmit="return validiere()">
<label>Name (2-50 Zeichen):<br>
<input type="text" name="name" id="name" required
minlength="2" maxlength="50"
pattern="[A-Za-zÄäÖöÜüß ]+">
</label><br><br>
<label>E-Mail:<br>
<input type="email" name="email" id="email" required>
</label><br><br>
<label>Alter (18-100):<br>
<input type="number" name="alter" id="alter"
min="18" max="100" required>
</label><br><br>
<label>Passwort (mind. 8 Zeichen):<br>
<input type="password" name="passwort" id="passwort"
required minlength="8">
</label><br><br>
<button type="submit">Registrieren</button>
</form>
<script>
function validiere() {
var name = document.getElementById('name').value;
var email = document.getElementById('email').value;
var alter = document.getElementById('alter').value;
var passwort = document.getElementById('passwort').value;
// Name prüfen
if (name.length < 2 || name.length > 50) {
alert('Name muss zwischen 2 und 50 Zeichen lang sein!');
return false;
}
// E-Mail prüfen
var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
alert('Bitte gültige E-Mail eingeben!');
return false;
}
// Alter prüfen
if (alter < 18 || alter > 100) {
alert('Alter muss zwischen 18 und 100 liegen!');
return false;
}
// Passwort prüfen
if (passwort.length < 8) {
alert('Passwort muss mindestens 8 Zeichen lang sein!');
return false;
}
return true; // Formular senden
}
</script>Serverseitige Validierung (PHP)
php
<?php
// verarbeite.php
$fehler = [];
$erfolg = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 1. Name validieren
$name = trim($_POST['name'] ?? '');
if (empty($name)) {
$fehler[] = "Name darf nicht leer sein.";
} elseif (strlen($name) < 2 || strlen($name) > 50) {
$fehler[] = "Name muss zwischen 2 und 50 Zeichen lang sein.";
} elseif (!preg_match('/^[A-Za-zÄäÖöÜüß ]+$/', $name)) {
$fehler[] = "Name darf nur Buchstaben und Leerzeichen enthalten.";
}
// 2. E-Mail validieren
$email = trim($_POST['email'] ?? '');
if (empty($email)) {
$fehler[] = "E-Mail darf nicht leer sein.";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$fehler[] = "Ungültige E-Mail-Adresse.";
}
// 3. Alter validieren
$alter = $_POST['alter'] ?? '';
if (empty($alter)) {
$fehler[] = "Alter darf nicht leer sein.";
} elseif (!is_numeric($alter)) {
$fehler[] = "Alter muss eine Zahl sein.";
} elseif ($alter < 18 || $alter > 100) {
$fehler[] = "Alter muss zwischen 18 und 100 liegen.";
}
// 4. Passwort validieren
$passwort = $_POST['passwort'] ?? '';
if (empty($passwort)) {
$fehler[] = "Passwort darf nicht leer sein.";
} elseif (strlen($passwort) < 8) {
$fehler[] = "Passwort muss mindestens 8 Zeichen lang sein.";
}
// Wenn keine Fehler: Erfolg!
if (empty($fehler)) {
$erfolg = true;
// Hier könnte man Daten in Datenbank speichern...
}
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Validierung</title>
<style>
.fehler { color: red; }
.erfolg { color: green; }
</style>
</head>
<body>
<?php if (!empty($fehler)): ?>
<div class="fehler">
<h3>Fehler:</h3>
<ul>
<?php foreach ($fehler as $f): ?>
<li><?php echo htmlspecialchars($f); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($erfolg): ?>
<div class="erfolg">
<h3>Erfolgreich registriert!</h3>
<p>Name: <?php echo htmlspecialchars($name); ?></p>
<p>E-Mail: <?php echo htmlspecialchars($email); ?></p>
</div>
<?php endif; ?>
<!-- Formular hier einfügen... -->
</body>
</html>9.5 XSS verhindern (htmlspecialchars)
Was ist XSS (Cross-Site Scripting)?
XSS ist eine Sicherheitslücke, bei der Angreifer bösartigen Code in Webseiten einschleusen.
Beispiel für XSS-Angriff:
php
<?php
// Schlechte Praxis (anfällig für XSS)
$name = $_GET['name'] ?? '';
echo "Willkommen " . $name; // Gefährlich!
// Wenn ein Angreifer folgende URL aufruft:
// index.php?name=<script>alert('XSS')</script>
// Dann wird das JavaScript ausgeführt!
?>
<!--
XSS-Schutzmassnahmen:
1. htmlspecialchars() verwenden
2. ENT_QUOTES flag verwenden (schützt auch einfache Anführungszeichen)
3. UTF-8 Encoding angeben
4. Immer vor Ausgabe escapen
-->XSS-Schutz mit htmlspecialchars()
php
<?php
// Richtig: htmlspecialchars() verwenden
$name = $_GET['name'] ?? '';
$name_sicher = htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
echo "Willkommen " . $name_sicher;
// Was htmlspecialchars() macht:
// & → &
// " → "
// ' → ' (mit ENT_QUOTES)
// < → <
// > → >
// Also wird aus <script>alert('XSS')</script>
// <script>alert('XSS')</script>
// Das wird im Browser als Text angezeigt, nicht ausgeführt!
// Für HTML-Attribute (value="" etc.)
$wert = htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
echo '<input type="text" value="' . $wert . '">';
// Für JSON-Ausgabe
$daten = ["name" => $name];
echo json_encode($daten, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
?>
<!--
Weitere XSS-Schutzmassnahmen:
1. Content Security Policy (CSP) Header setzen
2. Eingabedaten validieren (Server + Client)
3. Keine Benutzereingaben direkt in eval() oder exec() verwenden
4. Template-Systeme verwenden (die automatisch escapen)
-->9.6 Praxis: Login-Formular, Registrierungsformular
Login-Formular
php
<!-- login.html -->
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<?php if (isset($_GET['fehler'])): ?>
<p style="color: red;"><?php echo htmlspecialchars($_GET['fehler']); ?></p>
<?php endif; ?>
<form method="post" action="login_verarbeite.php">
<label>Benutzername:<br>
<input type="text" name="benutzer" required>
</label><br><br>
<label>Passwort:<br>
<input type="password" name="passwort" required>
</label><br><br>
<button type="submit">Einloggen</button>
</form>
<p>Noch kein Konto? <a href="registrierung.html">Hier registrieren</a></p>
</body>
</html>
<?php
// login_verarbeite.php
session_start();
header('Content-Type: text/html; charset=utf-8');
$fehler = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$benutzer = trim($_POST['benutzer'] ?? '');
$passwort = $_POST['passwort'] ?? '';
// Validierung
if (empty($benutzer)) {
$fehler[] = "Benutzername darf nicht leer sein.";
}
if (empty($passwort)) {
$fehler[] = "Passwort darf nicht leer sein.";
}
// Wenn keine Fehler: "Login" prüfen (Beispiel)
if (empty($fehler)) {
// In echtem Projekt: Datenbank abfragen!
$benutzer_korrekt = "max";
$passwort_hash = password_hash("geheim", PASSWORD_DEFAULT);
if ($benutzer === $benutzer_korrekt && password_verify($passwort, $passwort_hash)) {
// Login erfolgreich
$_SESSION['benutzer'] = $benutzer;
$_SESSION['eingeloggt'] = true;
header("Location: willkommen.php");
exit();
} else {
$fehler[] = "Benutzername oder Passwort falsch.";
}
}
}
// Fehler anzeigen (Weiterleitung zu login.html mit Fehlermeldung)
if (!empty($fehler)) {
$fehler_string = urlencode(implode("<br>", $fehler));
header("Location: login.html?fehler=" . $fehler_string);
exit();
}
?>Registrierungsformular
php
<!-- registrierung.html -->
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Registrierung</title>
</head>
<body>
<h2>Registrierung</h2>
<form method="post" action="registrierung_verarbeite.php">
<label>Benutzername:<br>
<input type="text" name="benutzer" required minlength="3" maxlength="20">
</label><br><br>
<label>E-Mail:<br>
<input type="email" name="email" required>
</label><br><br>
<label>Passwort:<br>
<input type="password" name="passwort" required minlength="8">
</label><br><br>
<label>Passwort bestätigen:<br>
<input type="password" name="passwort_bestätigen" required>
</label><br><br>
<button type="submit">Registrieren</button>
</form>
</body>
</html>
<?php
// registrierung_verarbeite.php
header('Content-Type: text/html; charset=utf-8');
$fehler = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$benutzer = trim($_POST['benutzer'] ?? '');
$email = trim($_POST['email'] ?? '');
$passwort = $_POST['passwort'] ?? '';
$passwort_bestätigen = $_POST['passwort_bestätigen'] ?? '';
// Validierung
if (empty($benutzer) || strlen($benutzer) < 3 || strlen($benutzer) > 20) {
$fehler[] = "Benutzername muss zwischen 3 und 20 Zeichen lang sein.";
}
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$fehler[] = "Gültige E-Mail-Adresse erforderlich.";
}
if (empty($passwort) || strlen($passwort) < 8) {
$fehler[] = "Passwort muss mindestens 8 Zeichen lang sein.";
}
if ($passwort !== $passwort_bestätigen) {
$fehler[] = "Passwörter stimmen nicht überein.";
}
// Wenn keine Fehler: Registrierung speichern (Beispiel)
if (empty($fehler)) {
// In echtem Projekt: Datenbank speichern!
$passwort_hash = password_hash($passwort, PASSWORD_DEFAULT);
// Simuliere Speicherung
echo "<h2>Registrierung erfolgreich!</h2>";
echo "Benutzername: " . htmlspecialchars($benutzer) . "<br>";
echo "E-Mail: " . htmlspecialchars($email) . "<br>";
echo "Passwort (Hash): " . $passwort_hash . "<br>";
echo "<p><a href='login.html'>Jetzt einloggen</a></p>";
exit();
}
}
// Fehler anzeigen
if (!empty($fehler)) {
echo "<h3>Fehler:</h3><ul>";
foreach ($fehler as $f) {
echo "<li>" . htmlspecialchars($f) . "</li>";
}
echo "</ul><p><a href='registrierung.html'>Zurück</a></p>";
}
?>Zusammenfassung
In diesem Kapitel haben Sie:
- ✅ Den Unterschied zwischen GET und POST verstanden
- ✅ Formulare mit
method="get"undmethod="post"erstellt - ✅ Daten mit
$_GET,$_POSTund$_REQUESTempfangen - ✅ Formulardaten validiert (Client- und Serverseitig)
- ✅ XSS-Angriffe mit
htmlspecialchars()verhindert - ✅ Praxisbeispiele (Login, Registrierung) erstellt
Nächstes Kapitel: Wir werden Session-Control lernen (Login-Status, Cookies).
Übungsaufgaben:
- Erstellen Sie ein Suchformular mit GET-Methode
- Erstellen Sie ein Kontaktformular mit POST-Methode und Validierung
- Schützen Sie ein Formular vor XSS-Angriffen
- Erstellen Sie ein Login-System mit Session-Verwaltung
Häufige Fehler:
- ❌ GET für Passwörter verwenden → Immer POST für sensible Daten!
- ❌ Benutzereingaben direkt ausgeben → Immer
htmlspecialchars()verwenden! - ❌
$_REQUESTverwenden → Immer spezifisch sein ($_GEToder$_POST)! - ❌ Validierung nur clientseitig → Immer auch serverseitig validieren!
