Appearance
Kapitel 14: Basis-Praxisprojekte
14.1 Praxis 1: Einfaches Gästebuch (Formular + Datenbank + Anzeige)
Projektübersicht
Ein einfaches Gästebuch, in dem Benutzer Nachrichten hinterlassen können.
Funktionen:
- Formular zur Eingabe von Name und Nachricht
- Speicherung in Datenbank
- Anzeige aller Nachrichten (chronologisch)
Schritt 1: Datenbank vorbereiten
sql
-- Datenbank: gaestebuch
CREATE DATABASE gaestebuch
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
USE gaestebuch;
-- Tabelle: eintraege
CREATE TABLE eintraege (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
nachricht TEXT NOT NULL,
erstellt_am DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;Schritt 2: Konfigurationsdatei (config.php)
php
<?php
// config.php
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'gaestebuch');
// Datenbankverbindung herstellen
function db_connect() {
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) {
die("Verbindungsfehler: " . $conn->connect_error);
}
$conn->set_charset("utf8mb4");
return $conn;
}
?>Schritt 3: Gästebuch-Formular (index.php)
php
<?php
// index.php
require_once 'config.php';
$erfolg = '';
$fehler = '';
// Formulardaten verarbeiten (INSERT)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$nachricht = trim($_POST['nachricht'] ?? '');
// Validierung
if (empty($name) || empty($nachricht)) {
$fehler = "Name und Nachricht dürfen nicht leer sein.";
} elseif (strlen($name) < 2 || strlen($name) > 100) {
$fehler = "Name muss zwischen 2 und 100 Zeichen lang sein.";
} elseif (strlen($nachricht) < 10) {
$fehler = "Nachricht muss mindestens 10 Zeichen lang sein.";
} else {
$conn = db_connect();
// Prepared Statement (SQL-Injection-Schutz)
$sql = "INSERT INTO eintraege (name, nachricht) VALUES (?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $name, $nachricht);
if ($stmt->execute()) {
$erfolg = "Nachricht erfolgreich hinterlassen!";
} else {
$fehler = "Fehler beim Speichern: " . $stmt->error;
}
$stmt->close();
$conn->close();
}
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gästebuch</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
.eintrag { background: #f9f9f9; padding: 15px; margin: 15px 0; border-radius: 5px; }
.name { font-weight: bold; color: #333; }
.datum { font-size: 0.9em; color: #777; }
.nachricht { margin-top: 10px; }
.erfolg { color: green; }
.fehler { color: red; }
</style>
</head>
<body>
<h1>📖 Gästebuch</h1>
<?php if ($erfolg): ?>
<p class="erfolg"><?php echo htmlspecialchars($erfolg); ?></p>
<?php endif; ?>
<?php if ($fehler): ?>
<p class="fehler"><?php echo htmlspecialchars($fehler); ?></p>
<?php endif; ?>
<h2>Nachricht hinterlassen</h2>
<form method="post" action="">
<label>Name:<br>
<input type="text" name="name" required minlength="2" maxlength="100">
</label><br><br>
<label>Nachricht:<br>
<textarea name="nachricht" rows="5" cols="50" required minlength="10"></textarea>
</label><br><br>
<button type="submit">Absenden</button>
</form>
<hr>
<h2>Alle Nachrichten</h2>
<?php
$conn = db_connect();
$sql = "SELECT * FROM eintraege ORDER BY erstellt_am DESC";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo '<div class="eintrag">';
echo '<div class="name">' . htmlspecialchars($row['name']) . '</div>';
echo '<div class="datum">' . date("d.m.Y H:i", strtotime($row['erstellt_am'])) . '</div>';
echo '<div class="nachricht">' . nl2br(htmlspecialchars($row['nachricht'])) . '</div>';
echo '</div>';
}
} else {
echo "<p>Noch keine Nachrichten vorhanden.</p>";
}
$result->free();
$conn->close();
?>
</body>
</html>14.2 Praxis 2: Benutzer-Login-System (Registrierung + Login + Logout)
Projektübersicht
Ein vollständiges Benutzer-Authentifizierungssystem.
Funktionen:
- Registrierung (mit Passwort-Hashing)
- Login (mit Session)
- Logout
- Geschützte Seiten
Schritt 1: Datenbank vorbereiten
sql
-- Datenbank: benutzer_system
CREATE DATABASE benutzer_system
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
USE benutzer_system;
-- Tabelle: benutzer
CREATE TABLE benutzer (
id INT AUTO_INCREMENT PRIMARY KEY,
benutzername VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(255) NOT NULL UNIQUE,
passwort VARCHAR(255) NOT NULL,
erstellt_am DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;Schritt 2: Registrierung (register.php)
php
<?php
// register.php
require_once 'config.php';
$erfolg = '';
$fehler = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$benutzername = trim($_POST['benutzername'] ?? '');
$email = trim($_POST['email'] ?? '');
$passwort = $_POST['passwort'] ?? '';
$passwort_bestätigen = $_POST['passwort_bestätigen'] ?? '';
// Validierung
if (empty($benutzername) || strlen($benutzername) < 3 || strlen($benutzername) > 50) {
$fehler[] = "Benutzername muss zwischen 3 und 50 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 durchführen
if (empty($fehler)) {
$conn = db_connect();
// Prüfen, ob Benutzername oder E-Mail bereits existiert
$sql = "SELECT id FROM benutzer WHERE benutzername = ? OR email = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $benutzername, $email);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
$fehler[] = "Benutzername oder E-Mail bereits registriert.";
} else {
// Passwort hashen
$passwort_hash = password_hash($passwort, PASSWORD_DEFAULT);
// Benutzer speichern
$sql = "INSERT INTO benutzer (benutzername, email, passwort) VALUES (?, ?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("sss", $benutzername, $email, $passwort_hash);
if ($stmt->execute()) {
$erfolg = "Registrierung erfolgreich! <a href='login.php'>Jetzt einloggen</a>";
} else {
$fehler[] = "Fehler bei der Registrierung.";
}
}
$stmt->close();
$conn->close();
}
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Registrierung</title>
</head>
<body>
<h1>📝 Registrierung</h1>
<?php if ($erfolg): ?>
<p style="color: green;"><?php echo $erfolg; ?></p>
<?php endif; ?>
<?php if (!empty($fehler)): ?>
<div style="color: red;">
<ul>
<?php foreach ($fehler as $f): ?>
<li><?php echo htmlspecialchars($f); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form method="post" action="">
<label>Benutzername:<br>
<input type="text" name="benutzername" required minlength="3" maxlength="50">
</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>
<p>Bereits registriert? <a href="login.php">Hier einloggen</a></p>
</body>
</html>Schritt 3: Login (login.php)
php
<?php
// login.php
session_start();
require_once 'config.php';
$fehler = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$benutzername = trim($_POST['benutzername'] ?? '');
$passwort = $_POST['passwort'] ?? '';
if (empty($benutzername) || empty($passwort)) {
$fehler[] = "Benutzername und Passwort dürfen nicht leer sein.";
} else {
$conn = db_connect();
// Benutzer suchen
$sql = "SELECT id, benutzername, passwort FROM benutzer WHERE benutzername = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $benutzername);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows === 1) {
$stmt->bind_result($id, $benutzername_db, $passwort_hash);
$stmt->fetch();
// Passwort verifizieren
if (password_verify($passwort, $passwort_hash)) {
// Login erfolgreich: Session-Variablen setzen
session_regenerate_id(true); // Session-Fixation-Schutz
$_SESSION['benutzer_id'] = $id;
$_SESSION['benutzername'] = $benutzername_db;
$_SESSION['eingeloggt'] = true;
header("Location: dashboard.php");
exit();
} else {
$fehler[] = "Benutzername oder Passwort falsch.";
}
} else {
$fehler[] = "Benutzername oder Passwort falsch.";
}
$stmt->close();
$conn->close();
}
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h1>🔐 Login</h1>
<?php if (!empty($fehler)): ?>
<div style="color: red;">
<ul>
<?php foreach ($fehler as $f): ?>
<li><?php echo htmlspecialchars($f); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form method="post" action="">
<label>Benutzername:<br>
<input type="text" name="benutzername" 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="register.php">Hier registrieren</a></p>
</body>
</html>Schritt 4: Geschützte Seite (dashboard.php)
php
<?php
// dashboard.php
session_start();
// Prüfen, ob Benutzer eingeloggt ist
if (!isset($_SESSION['eingeloggt']) || $_SESSION['eingeloggt'] !== true) {
header("Location: login.php");
exit();
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Dashboard</title>
</head>
<body>
<h1>👤 Willkommen, <?php echo htmlspecialchars($_SESSION['benutzername']); ?>!</h1>
<p>Dies ist eine geschützte Seite. Nur eingeloggte Benutzer können sie sehen.</p>
<p><a href="logout.php">Ausloggen</a></p>
</body>
</html>Schritt 5: Logout (logout.php)
php
<?php
// logout.php
session_start();
// Session-Variablen löschen
$_SESSION = array();
// Session-Cookie löschen
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Session zerstören
session_destroy();
// Zur Login-Seite weiterleiten
header("Location: login.php");
exit();
?>14.3 Praxis 3: Warenliste (Array-Verarbeitung + Anzeige)
Projektübersicht
Eine einfache Warenliste (Warenkorb) zur Demonstration von Array-Verarbeitung.
Funktionen:
- Waren hinzufügen
- Waren anzeigen
- Gesamtpreis berechnen
- Waren entfernen
Warenkorb-System (warenkorb.php)
php
<?php
// warekorb.php
session_start();
// Warenkorb initialisieren (wenn noch nicht vorhanden)
if (!isset($_SESSION['warenkorb'])) {
$_SESSION['warenkorb'] = [];
}
$erfolg = '';
$fehler = '';
// Waren hinzufügen
if (isset($_GET['hinzufuegen'])) {
$produkt_id = (int) $_GET['hinzufuegen'];
// Produktdaten (in echtem Projekt aus Datenbank)
$produkte = [
1 => ['name' => 'T-Shirt', 'preis' => 19.99],
2 => ['name' => 'Jeans', 'preis' => 49.99],
3 => ['name' => 'Sneaker', 'preis' => 79.99]
];
if (isset($produkte[$produkt_id])) {
// Prüfen, ob Produkt bereits im Warenkorb ist
if (isset($_SESSION['warenkorb'][$produkt_id])) {
$_SESSION['warenkorb'][$produkt_id]['menge']++;
} else {
$_SESSION['warenkorb'][$produkt_id] = [
'name' => $produkte[$produkt_id]['name'],
'preis' => $produkte[$produkt_id]['preis'],
'menge' => 1
];
}
$erfolg = $produkte[$produkt_id]['name'] . " wurde dem Warenkorb hinzugefügt!";
} else {
$fehler = "Produkt nicht gefunden!";
}
}
// Waren entfernen
if (isset($_GET['entfernen'])) {
$produkt_id = (int) $_GET['entfernen'];
if (isset($_SESSION['warenkorb'][$produkt_id])) {
$name = $_SESSION['warenkorb'][$produkt_id]['name'];
unset($_SESSION['warenkorb'][$produkt_id]);
$erfolg = $name . " wurde aus dem Warenkorb entfernt!";
}
}
// Warenkorb leeren
if (isset($_GET['leeren'])) {
$_SESSION['warenkorb'] = [];
$erfolg = "Warenkorb wurde geleert!";
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Warenkorb</title>
<style>
body { font-family: Arial, sans-serif; max-width: 1000px; margin: 50px auto; padding: 20px; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }
th { background-color: #f2f2f2; }
.erfolg { color: green; }
.fehler { color: red; }
</style>
</head>
<body>
<h1>🛒 Warenkorb</h1>
<?php if ($erfolg): ?>
<p class="erfolg"><?php echo htmlspecialchars($erfolg); ?></p>
<?php endif; ?>
<?php if ($fehler): ?>
<p class="fehler"><?php echo htmlspecialchars($fehler); ?></p>
<?php endif; ?>
<h2>Verfügbare Produkte</h2>
<ul>
<li><a href="?hinzufuegen=1">T-Shirt (19,99 €)</a></li>
<li><a href="?hinzufuegen=2">Jeans (49,99 €)</a></li>
<li><a href="?hinzufuegen=3">Sneaker (79,99 €)</a></li>
</ul>
<hr>
<h2>Dein Warenkorb</h2>
<?php if (empty($_SESSION['warenkorb'])): ?>
<p>Dein Warenkorb ist leer.</p>
<?php else: ?>
<table>
<tr>
<th>Produkt</th>
<th>Einzelpreis</th>
<th>Menge</th>
<th>Gesamtpreis</th>
<th>Aktion</th>
</tr>
<?php
$gesamtpreis = 0;
foreach ($_SESSION['warenkorb'] as $id => $produkt):
$produkt_gesamt = $produkt['preis'] * $produkt['menge'];
$gesamtpreis += $produkt_gesamt;
?>
<tr>
<td><?php echo htmlspecialchars($produkt['name']); ?></td>
<td><?php echo number_format($produkt['preis'], 2, ',', '.'); ?> €</td>
<td><?php echo $produkt['menge']; ?></td>
<td><?php echo number_format($produkt_gesamt, 2, ',', '.'); ?> €</td>
<td><a href="?entfernen=<?php echo $id; ?>" onclick="return confirm('Wirklich entfernen?')">Entfernen</a></td>
</tr>
<?php endforeach; ?>
<tr>
<td colspan="3"><strong>Gesamtpreis:</strong></td>
<td><strong><?php echo number_format($gesamtpreis, 2, ',', '.'); ?> €</strong></td>
<td></td>
</tr>
</table>
<p><a href="?leeren=1" onclick="return confirm('Warenkorb wirklich leeren?')">Warenkorb leeren</a></p>
<?php endif; ?>
<p><a href="index.php">Weiter einkaufen</a></p>
</body>
</html>Zusammenfassung
In diesem Kapitel haben Sie:
- ✅ Ein einfaches Gästebuch mit Formular, Datenbank und Anzeige erstellt
- ✅ Ein vollständiges Benutzer-Login-System (Registrierung, Login, Logout) implementiert
- ✅ Einen Warenkorb (Warenliste) mit Array-Verarbeitung und Anzeige erstellt
Nächstes Kapitel: Wir werden vollständige Praxisprojekte (Blog-System, CMS) erstellen.
Übungsaufgaben:
- Erweitern Sie das Gästebuch um eine Löschfunktion (nur für Admins)
- Fügen Sie dem Login-System eine "Angemeldet bleiben"-Funktion hinzu (mit Cookies)
- Erweitern Sie den Warenkorb um Mengenänderung (Eingabefeld)
- Fügen Sie dem Warenkorb eine Versandkostenberechnung hinzu
Häufige Fehler:
- ❌
password_hash()vergessen → Passwörter IMMER hashen! - ❌
session_regenerate_id()vergessen → Session-Fixation-Angriff! - ❌
htmlspecialchars()bei Ausgabe vergessen → XSS-Angriff! - ❌
exit()nachheader("Location: ...")vergessen → Code wird weiter ausgeführt!
