Skip to content

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:

  1. Formular zur Eingabe von Name und Nachricht
  2. Speicherung in Datenbank
  3. 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:

  1. Registrierung (mit Passwort-Hashing)
  2. Login (mit Session)
  3. Logout
  4. 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:

  1. Waren hinzufügen
  2. Waren anzeigen
  3. Gesamtpreis berechnen
  4. 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:

  1. Erweitern Sie das Gästebuch um eine Löschfunktion (nur für Admins)
  2. Fügen Sie dem Login-System eine "Angemeldet bleiben"-Funktion hinzu (mit Cookies)
  3. Erweitern Sie den Warenkorb um Mengenänderung (Eingabefeld)
  4. 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() nach header("Location: ...") vergessen → Code wird weiter ausgeführt!

Frei für alle Anfänger