Skip to content

Kapitel 17: Häufig verwendete Funktionen entwickeln

17.1 E-Mail senden

E-Mail senden mit mail()-Funktion

php
<?php
    // Einfache E-Mail senden
    $an = "empfaenger@example.com";
    $betreff = "Test-E-Mail";
    $nachricht = "Dies ist eine Test-E-Mail von PHP.";
    $header = "From: absender@example.com" . "\r\n" .
               "Reply-To: absender@example.com" . "\r\n" .
               "X-Mailer: PHP/" . phpversion();
    
    if (mail($an, $betreff, $nachricht, $header)) {
        echo "E-Mail erfolgreich gesendet!";
    } else {
        echo "Fehler beim Senden der E-Mail.";
    }
?>

E-Mail senden mit PHPMailer (empfohlen!)

PHPMailer: Eine beliebte Bibliothek für E-Mail-Versand in PHP.

1. PHPMailer installieren (mit Composer)

bash
composer require phpmailer/phpmailer

2. E-Mail senden mit PHPMailer (SMTP)

php
<?php
    // PHPMailer verwenden
    require_once 'vendor/autoload.php';
    
    use PHPMailer\PHPMailer\PHPMailer;
    use PHPMailer\PHPMailer\Exception;
    
    $mail = new PHPMailer(true);
    
    try {
        // Servereinstellungen
        $mail->SMTPDebug = 0;                      // Debug-Ausgabe (0 = aus)
        $mail->isSMTP();                            // SMTP verwenden
        $mail->Host       = 'smtp.example.com';      // SMTP-Server
        $mail->SMTPAuth   = true;                   // SMTP-Authentifizierung
        $mail->Username   = 'absender@example.com';  // SMTP-Benutzername
        $mail->Password   = 'passwort';             // SMTP-Passwort
        $mail->SMTPSecure = PHPMailer::ENCRYPTION_SSTART;  // Verschlüsselung
        $mail->Port       = 587;                    // SMTP-Port
        
        // Empfänger
        $mail->setFrom('absender@example.com', 'Absender Name');
        $mail->addAddress('empfaenger@example.com', 'Empfänger Name');
        $mail->addReplyTo('absender@example.com', 'Absender Name');
        
        // Inhalt
        $mail->isHTML(true);                                  // HTML-E-Mail
        $mail->Subject = 'Test-E-Mail von PHPMailer';
        $mail->Body    = '<h1>Test-E-Mail</h1><p>Dies ist eine Test-E-Mail von PHPMailer.</p>';
        $mail->AltBody = 'Dies ist eine Test-E-Mail von PHPMailer.';  // Text-Version
        
        // Anhang
        // $mail->addAttachment('/pfad/zu/datei.pdf');
        
        $mail->send();
        echo 'E-Mail erfolgreich gesendet!';
        
    } catch (Exception $e) {
        echo "E-Mail konnte nicht gesendet werden. Fehler: {$mail->ErrorInfo}";
    }
?>

17.2 Captcha

Was ist Captcha?

Captcha: Ein Test, um zu überprüfen, ob ein Benutzer ein Mensch ist (und kein Bot).

Einfaches Captcha (matematisches Rätsel)

php
<?php
    session_start();
    
    // Captcha generieren
    if (!isset($_SESSION['captcha_antwort'])) {
        $zahl1 = rand(1, 10);
        $zahl2 = rand(1, 10);
        $_SESSION['captcha_antwort'] = $zahl1 + $zahl2;
    }
    
    // Formular
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $captcha_eingabe = (int) ($_POST['captcha'] ?? 0);
        
        if ($captcha_eingabe === $_SESSION['captcha_antwort']) {
            echo "Captcha korrekt!";
            unset($_SESSION['captcha_antwort']);  // Captcha zurückseten
        } else {
            echo "Captcha falsch!";
        }
    }
?>

<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>Captcha-Beispiel</title>
</head>
<body>
    <form method="post" action="">
        <p>Captcha: Was ist <?php echo $zahl1 . " + " . $zahl2; ?>?</p>
        <label>Antwort:<br>
            <input type="text" name="captcha" required>
        </label><br><br>
        
        <button type="submit">Senden</button>
    </form>
</body>
</html>

Google reCAPTCHA v3 (empfohlen!)

1. reCAPTCHA-Keys erhalten

  1. Gehen Sie zu Google reCAPTCHA
  2. Registrieren Sie Ihre Webseite
  3. Erhalten Sie Site Key und Secret Key

2. reCAPTCHA in Formular einbinden

html
<!-- formular.html -->
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>reCAPTCHA-Beispiel</title>
    <script src="https://www.google.com/recaptcha/api.js?render=DEIN_SITE_KEY"></script>
</head>
<body>
    <form id="meinFormular" method="post" action="verarbeite.php">
        <label>Name:<br>
            <input type="text" name="name" required>
        </label><br><br>
        
        <button type="submit">Senden</button>
    </form>
    
    <script>
        grecaptcha.ready(function() {
            grecaptcha.execute('DEIN_SITE_KEY', {action: 'senden'}).then(function(token) {
                // Token in verstecktes Feld einfügen
                var input = document.createElement('input');
                input.type = 'hidden';
                input.name = 'g-recaptcha-response';
                input.value = token;
                document.getElementById('meinFormular').appendChild(input);
            });
        });
    </script>
</body>
</html>

3. reCAPTCHA auf Server-Seite verifizieren

php
<?php
    // verarbeite.php
    session_start();
    
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $name = trim($_POST['name'] ?? '');
        $recaptcha_token = $_POST['g-recaptcha-response'] ?? '';
        
        // reCAPTCHA verifizieren
        $secret_key = 'DEIN_SECRET_KEY';
        $url = 'https://www.google.com/recaptcha/api/siteverify';
        $daten = [
            'secret'   => $secret_key,
            'response' => $recaptcha_token,
            'remoteip' => $_SERVER['REMOTE_ADDR']
        ];
        
        $options = [
            'http' => [
                'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
                'method'  => 'POST',
                'content' => http_build_query($daten)
            ]
        ];
        
        $context  = stream_context_create($options);
        $result = file_get_contents($url, false, $context);
        $result_json = json_decode($result);
        
        if ($result_json->success && $result_json->score >= 0.5) {
            // Captcha bestanden
            echo "Captcha bestanden! Name: " . htmlspecialchars($name);
        } else {
            // Captcha nicht bestanden (Bot-Verdacht)
            echo "Captcha nicht bestanden! (Bot-Verdacht)";
        }
    }
?>

17.3 Paginierung (Seitenaufteilung)

Was ist Paginierung?

Paginierung: Eine Methode, um grosse Datenmengen auf mehrere Seiten aufzuteilen.

Einfache Paginierung

php
<?php
    // Paginierung
    $conn = new mysqli("localhost", "root", "", "meine_datenbank");
    $conn->set_charset("utf8mb4");
    
    // Seitennummer aus URL holen (Standard: Seite 1)
    $seite = (int) ($_GET['seite'] ?? 1);
    $seite = max(1, $seite);  // Mindestens Seite 1
    
    // Anzahl Einträge pro Seite
    $eintraege_pro_seite = 10;
    
    // Offset berechnen
    $offset = ($seite - 1) * $eintraege_pro_seite;
    
    // Gesamtanzahl der Einträge
    $sql_gesamt = "SELECT COUNT(*) as gesamt FROM artikel";
    $result_gesamt = $conn->query($sql_gesamt);
    $row_gesamt = $result_gesamt->fetch_assoc();
    $gesamteintraege = $row_gesamt['gesamt'];
    
    // Gesamtanzahl der Seiten
    $gesamteiten = ceil($gesamteintraege / $eintraege_pro_seite);
    
    // Artikel für aktuelle Seite abfragen
    $sql = "SELECT * FROM artikel ORDER BY erstellt_am DESC LIMIT ? OFFSET ?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("ii", $eintraege_pro_seite, $offset);
    $stmt->execute();
    $result = $stmt->get_result();
    
    // Artikel anzeigen
    while ($row = $result->fetch_assoc()) {
        echo "<h3>" . htmlspecialchars($row['titel']) . "</h3>";
        echo "<p>" . htmlspecialchars($row['inhalt']) . "</p>";
        echo "<hr>";
    }
    
    // Paginierungs-Links anzeigen
    echo "<div class='paginierung'>";
    
    // Zurück-Button
    if ($seite > 1) {
        echo "<a href='?seite=" . ($seite - 1) . "'>Zurück</a> ";
    }
    
    // Seitennummern
    for ($i = 1; $i <= $gesamteiten; $i++) {
        if ($i === $seite) {
            echo "<strong>$i</strong> ";
        } else {
            echo "<a href='?seite=$i'>$i</a> ";
        }
    }
    
    // Weiter-Button
    if ($seite < $gesamteiten) {
        echo "<a href='?seite=" . ($seite + 1) . "'>Weiter</a> ";
    }
    
    echo "</div>";
    
    $stmt->close();
    $conn->close();
?>

Paginierung mit Bootstrap (responsive)

html
<!-- In <head> -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">

<!-- Paginierung -->
<nav aria-label="Paginierung">
    <ul class="pagination justify-content-center">
        <li class="page-item <?php echo $seite <= 1 ? 'disabled' : ''; ?>">
            <a class="page-link" href="?seite=<?php echo $seite - 1; ?>">Zurück</a>
        </li>
        
        <?php for ($i = 1; $i <= $gesamteiten; $i++): ?>
            <li class="page-item <?php echo $i === $seite ? 'active' : ''; ?>">
                <a class="page-link" href="?seite=<?php echo $i; ?>"><?php echo $i; ?></a>
            </li>
        <?php endfor; ?>
        
        <li class="page-item <?php echo $seite >= $gesamteiten ? 'disabled' : ''; ?>">
            <a class="page-link" href="?seite=<?php echo $seite + 1; ?>">Weiter</a>
        </li>
    </ul>
</nav>

17.4 API-Entwicklung (JSON-Rückgabe)

Was ist eine API?

API (Application Programming Interface): Eine Schnittstelle, über die Anwendungen miteinander kommunizieren können.

Einfache JSON-API erstellen

php
<?php
    // api/artikel.php
    header('Content-Type: application/json; charset=utf-8');
    
    require_once '../config.php';
    
    $conn = db_connect();
    
    // Alle Artikel abfragen
    $sql = "SELECT * FROM artikel ORDER BY erstellt_am DESC";
    $result = $conn->query($sql);
    
    $artikel = [];
    
    while ($row = $result->fetch_assoc()) {
        $artikel[] = [
            'id' => $row['id'],
            'titel' => $row['titel'],
            'inhalt' => $row['inhalt'],
            'erstellt_am' => $row['erstellt_am']
        ];
    }
    
    // JSON ausgeben
    echo json_encode($artikel, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    
    $conn->close();
?>

API mit Parametern (GET/POST)

php
<?php
    // api/artikel.php?id=1
    header('Content-Type: application/json; charset=utf-8');
    
    require_once '../config.php';
    
    $conn = db_connect();
    
    // ID aus URL holen
    $id = (int) ($_GET['id'] ?? 0);
    
    if ($id > 0) {
        // Einzelnen Artikel abfragen
        $sql = "SELECT * FROM artikel WHERE id = ?";
        $stmt = $conn->prepare($sql);
        $stmt->bind_param("i", $id);
        $stmt->execute();
        $result = $stmt->get_result();
        
        if ($result->num_rows === 1) {
            $row = $result->fetch_assoc();
            $artikel = [
                'id' => $row['id'],
                'titel' => $row['titel'],
                'inhalt' => $row['inhalt'],
                'erstellt_am' => $row['erstellt_am']
            ];
            
            echo json_encode($artikel, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
        } else {
            http_response_code(404);
            echo json_encode(['fehler' => 'Artikel nicht gefunden']);
        }
        
        $stmt->close();
    } else {
        // Alle Artikel abfragen
        $sql = "SELECT * FROM artikel ORDER BY erstellt_am DESC";
        $result = $conn->query($sql);
        
        $artikel = [];
        
        while ($row = $result->fetch_assoc()) {
            $artikel[] = [
                'id' => $row['id'],
                'titel' => $row['titel'],
                'inhalt' => $row['inhalt'],
                'erstellt_am' => $row['erstellt_am']
            ];
        }
        
        echo json_encode($artikel, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    }
    
    $conn->close();
?>

API mit POST (Daten speichern)

php
<?php
    // api/artikel_speichern.php
    header('Content-Type: application/json; charset=utf-8');
    
    require_once '../config.php';
    
    // Nur POST-Anfragen erlauben
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        http_response_code(405);
        echo json_encode(['fehler' => 'Nur POST-Anfragen erlaubt']);
        exit();
    }
    
    // JSON-Daten aus Request-Body lesen
    $json_daten = file_get_contents('php://input');
    $daten = json_decode($json_daten, true);
    
    if (!$daten) {
        http_response_code(400);
        echo json_encode(['fehler' => 'Ungültige JSON-Daten']);
        exit();
    }
    
    $titel = trim($daten['titel'] ?? '');
    $inhalt = trim($daten['inhalt'] ?? '');
    
    // Validierung
    if (empty($titel) || empty($inhalt)) {
        http_response_code(400);
        echo json_encode(['fehler' => 'Titel und Inhalt dürfen nicht leer sein']);
        exit();
    }
    
    $conn = db_connect();
    
    // Artikel speichern
    $sql = "INSERT INTO artikel (titel, inhalt, benutzer_id) VALUES (?, ?, ?)";
    $stmt = $conn->prepare($sql);
    $benutzer_id = 1;  // Beispiel
    $stmt->bind_param("ssi", $titel, $inhalt, $benutzer_id);
    
    if ($stmt->execute()) {
        http_response_code(201);
        echo json_encode([
            'erfolg' => true,
            'id' => $stmt->insert_id,
            'nachricht' => 'Artikel erfolgreich gespeichert'
        ]);
    } else {
        http_response_code(500);
        echo json_encode(['fehler' => 'Fehler beim Speichern: ' . $stmt->error]);
    }
    
    $stmt->close();
    $conn->close();
?>

17.5 AJAX-Interaktion (ohne Neuladen)

Was ist AJAX?

AJAX (Asynchronous JavaScript and XML): Eine Methode, um Daten im Hintergrund (asynchron) zu senden/empfangen, ohne die Seite neu zu laden.

Einfaches AJAX-Beispiel (mit Vanilla JavaScript)

html
<!-- index.html -->
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>AJAX-Beispiel</title>
</head>
<body>
    <h2>AJAX-Beispiel</h2>
    
    <button id="ladenButton">Artikel laden</button>
    
    <div id="artikelListe"></div>
    
    <script>
        document.getElementById('ladenButton').addEventListener('click', function() {
            // AJAX-Request (mit Fetch API)
            fetch('api/artikel.php')
                .then(response => response.json())
                .then(daten => {
                    // Daten verarbeiten
                    let html = '';
                    daten.forEach(artikel => {
                        html += '<h3>' + artikel.titel + '</h3>';
                        html += '<p>' + artikel.inhalt + '</p>';
                        html += '<hr>';
                    });
                    
                    document.getElementById('artikelListe').innerHTML = html;
                })
                .catch(fehler => {
                    console.error('Fehler:', fehler);
                });
        });
    </script>
</body>
</html>

AJAX mit jQuery (einfacher)

html
<!-- In <head> -->
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>

<!-- AJAX mit jQuery -->
<script>
    $(document).ready(function() {
        $('#ladenButton').click(function() {
            $.ajax({
                url: 'api/artikel.php',
                type: 'GET',
                dataType: 'json',
                success: function(daten) {
                    // Daten verarbeiten
                    let html = '';
                    daten.forEach(function(artikel) {
                        html += '<h3>' + artikel.titel + '</h3>';
                        html += '<p>' + artikel.inhalt + '</p>';
                        html += '<hr>';
                    });
                    
                    $('#artikelListe').html(html);
                },
                error: function(xhr, status, fehler) {
                    console.error('Fehler:', fehler);
                }
            });
        });
    });
</script>

AJAX-Formular (Daten senden ohne Neuladen)

html
<!-- formular.html -->
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>AJAX-Formular</title>
    <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
</head>
<body>
    <h2>AJAX-Formular</h2>
    
    <form id="meinFormular">
        <label>Name:<br>
            <input type="text" name="name" id="name" required>
        </label><br><br>
        
        <label>Nachricht:<br>
            <textarea name="nachricht" id="nachricht" required></textarea>
        </label><br><br>
        
        <button type="submit">Senden</button>
    </form>
    
    <div id="ergebnis"></div>
    
    <script>
        $(document).ready(function() {
            $('#meinFormular').submit(function(e) {
                e.preventDefault();  // Formular-Submit verhindern
                
                // Formulardaten sammeln
                let name = $('#name').val();
                let nachricht = $('#nachricht').val();
                
                // AJAX-Request senden
                $.ajax({
                    url: 'api/nachricht_speichern.php',
                    type: 'POST',
                    data: {
                        name: name,
                        nachricht: nachricht
                    },
                    success: function(antwort) {
                        $('#ergebnis').html('<p style="color: green;">' + antwort.nachricht + '</p>');
                        $('#meinFormular')[0].reset();  // Formular zurückseten
                    },
                    error: function(xhr, status, fehler) {
                        $('#ergebnis').html('<p style="color: red;">Fehler: ' + fehler + '</p>');
                    }
                });
            });
        });
    </script>
</body>
</html>
php
<?php
    // api/nachricht_speichern.php
    header('Content-Type: application/json; charset=utf-8');
    
    require_once '../config.php';
    
    // Nur POST-Anfragen erlauben
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        http_response_code(405);
        echo json_encode(['fehler' => 'Nur POST-Anfragen erlaubt']);
        exit();
    }
    
    $name = trim($_POST['name'] ?? '');
    $nachricht = trim($_POST['nachricht'] ?? '');
    
    // Validierung
    if (empty($name) || empty($nachricht)) {
        http_response_code(400);
        echo json_encode(['fehler' => 'Name und Nachricht dürfen nicht leer sein']);
        exit();
    }
    
    $conn = db_connect();
    
    // Nachricht speichern
    $sql = "INSERT INTO nachrichten (name, nachricht) VALUES (?, ?)";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("ss", $name, $nachricht);
    
    if ($stmt->execute()) {
        echo json_encode([
            'erfolg' => true,
            'nachricht' => 'Nachricht erfolgreich gespeichert!'
        ]);
    } else {
        http_response_code(500);
        echo json_encode(['fehler' => 'Fehler beim Speichern: ' . $stmt->error]);
    }
    
    $stmt->close();
    $conn->close();
?>

Zusammenfassung

In diesem Kapitel haben Sie:

  • ✅ E-Mails mit mail() und PHPMailer gesendet
  • ✅ Captcha (matematisches Rätsel und Google reCAPTCHA) implementiert
  • ✅ Paginierung (Seitenaufteilung) erstellt
  • ✅ JSON-API entwickelt (GET/POST, JSON-Rückgabe)
  • ✅ AJAX-Interaktion (ohne Neuladen) implementiert

Nächstes Kapitel: Wir werden häufige Fehler und Lösungen lernen.


Übungsaufgaben:

  1. Erstellen Sie ein Kontaktformular mit E-Mail-Versand (PHPMailer)
  2. Implementieren Sie Google reCAPTCHA v3 in ein Formular
  3. Erstellen Sie eine Paginierung für eine Artikelliste
  4. Entwickeln Sie eine JSON-API für ein Blog-System
  5. Erstellen Sie ein AJAX-Formular für Benutzerregistrierung

Häufige Fehler:

  • mail() in Produktion verwenden → Immer PHPMailer oder ähnliche Bibliotheken verwenden!
  • ❌ Captcha nicht validieren → Bots können Formulare automatisiert ausfüllen!
  • LIMIT und OFFSET in SQL-Abfragen vergessen → Paginierung funktioniert nicht!
  • header('Content-Type: application/json') vergessen → API gibt HTML statt JSON zurück!
  • e.preventDefault() in AJAX-Formularen vergessen → Seite wird neu geladen!

Frei für alle Anfänger