Donnerstag, 11 Dezember 2025

Diese Woche am beliebtesten

Vertiefendes Material

das Short Book

Willkommen beim Dreamcodes Short Gästebuch. Hier kannst du persönliche Nachrichten, Grüße oder Feedback hinterlassen, die für andere Besucher sichtbar sind. Jede Nachricht wird mit dem Namen des Verfassers und dem Datum der Eintragung angezeigt, sodass ein Überblick über alle Einträge leicht möglich ist.

Funktionsweise

Wenn du eine Nachricht einträgst, wird sie sicher in der Datenbank gespeichert und sofort im Gästebuch angezeigt. Jede Eintragung enthält den Namen, die Nachricht selbst und den Zeitpunkt der Erstellung. Um Spam und automatisierte Einträge zu vermeiden, gibt es eine einfache Captcha-Abfrage, die vor dem Absenden gelöst werden muss.

Verwaltung und Sicherheit

Ein Administrator hat die Möglichkeit, Einträge jederzeit zu löschen, insbesondere um Spam oder unerwünschte Inhalte zu entfernen. Alle Einträge werden sicher gespeichert und sind nur über diese Gästebuchseite einsehbar. Gelöschte Einträge können nicht wiederhergestellt werden.

Vorteile

  • Einfaches Hinzufügen von Einträgen: Name und Nachricht eingeben, Captcha lösen, absenden
  • Sichtbare Historie: Alle bisherigen Nachrichten werden in chronologischer Reihenfolge angezeigt
  • Admin-Kontrolle: Unerwünschte Einträge können sofort gelöscht werden
  • Spam-Schutz: Ein simples Captcha verhindert automatisierte Einträge
<?php
define('DB_FILE', __DIR__ . '/guestbook.sqlite');

// Initialize DB
$db = new SQLite3(DB_FILE);
$db->exec("CREATE TABLE IF NOT EXISTS entries (
    id INTEGER PRIMARY KEY,
    name TEXT,
    message TEXT,
    created_at INTEGER
)");

function escape($str){ return htmlspecialchars($str, ENT_QUOTES,'UTF-8'); }

function jsonResponse($data,$code=200){
    http_response_code($code);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($data);
    exit;
}

// Handle new entry
if($_SERVER['REQUEST_METHOD']==='POST' && isset($_GET['action']) && $_GET['action']==='add'){
    $name = trim($_POST['name'] ?? '');
    $message = trim($_POST['message'] ?? '');
    if(!$name || !$message) jsonResponse(['error'=>'Name und Nachricht erforderlich'],400);

    // Optional: simple captcha
    if(isset($_POST['captcha'])){
        if(trim($_POST['captcha']) !== '5') jsonResponse(['error'=>'Captcha falsch'],400);
    }

    $stmt = $db->prepare('INSERT INTO entries (name,message,created_at) VALUES (:name,:message,:created_at)');
    $stmt->bindValue(':name',$name,SQLITE3_TEXT);
    $stmt->bindValue(':message',$message,SQLITE3_TEXT);
    $stmt->bindValue(':created_at',time(),SQLITE3_INTEGER);
    $stmt->execute();
    jsonResponse(['success'=>true]);
}

// Admin delete
if($_SERVER['REQUEST_METHOD']==='POST' && isset($_GET['action']) && $_GET['action']==='delete'){
    $id = intval($_POST['id'] ?? 0);
    if($id<=0) jsonResponse(['error'=>'Ungültige ID'],400);
    $stmt = $db->prepare('DELETE FROM entries WHERE id=:id');
    $stmt->bindValue(':id',$id,SQLITE3_INTEGER);
    $stmt->execute();
    jsonResponse(['success'=>true]);
}

// Fetch entries
if(isset($_GET['action']) && $_GET['action']==='list'){
    $res = $db->query('SELECT * FROM entries ORDER BY created_at DESC');
    $entries=[];
    while($row=$res->fetchArray(SQLITE3_ASSOC)){
        $entries[]=[
            'id'=>$row['id'],
            'name'=>escape($row['name']),
            'message'=>escape($row['message']),
            'created_at'=>date('d.m.Y H:i',$row['created_at'])
        ];
    }
    jsonResponse($entries);
}

// Serve UI
?>
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Dreamcodes Short Gästebuch</title>
<style>
:root{--bg:#0f1724;--card:#0b1220;--accent:#7c3aed;--muted:#9aa4b2;--glass: rgba(255,255,255,0.03);}
body{font-family:Inter, sans-serif;background:linear-gradient(180deg,var(--bg),#071028);color:#e6eef8;margin:0;padding:40px;}
.container{max-width:800px;margin:0 auto}
.card{background:linear-gradient(180deg,var(--card),#071022);padding:28px;border-radius:16px;box-shadow:0 10px 30px rgba(2,6,23,0.7);margin-bottom:24px}
h1{font-size:24px;margin:0 0 8px}
p.lead{color:var(--muted);margin:0 0 20px}
.inputtext{background:transparent;border:1px solid rgba(255,255,255,0.04);padding:8px 10px;border-radius:8px;color:inherit;width:100%;margin-bottom:10px}
.btn{background:var(--accent);color:white;padding:10px 14px;border-radius:10px;border:none;cursor:pointer;font-weight:600}
.entry{padding:12px;margin-bottom:12px;background:rgba(255,255,255,0.02);border-radius:10px}
.entry-meta{font-size:13px;color:var(--muted)}
.deleteBtn{background:#ff4c4c;padding:4px 8px;font-size:12px;border-radius:6px;margin-left:10px;cursor:pointer}
footer{margin-top:18px;text-align:center;color:var(--muted);font-size:13px}
.thin{opacity:0.8}
</style>
</head>
<body>
<div class="container">
<div class="card">
<h1>Gästebuch</h1>
<p class="lead">Hinterlasse eine Nachricht oder Grüße für andere Besucher</p>
<input id="name" class="inputtext" type="text" placeholder="Dein Name">
<textarea id="message" class="inputtext" placeholder="Deine Nachricht"></textarea>
<label class="small">Captcha: Was ist 2 + 3? (Anti-Spam)</label>
<input id="captcha" class="inputtext" type="text" placeholder="Antwort">
<button id="submitBtn" class="btn">Absenden</button>
<div id="error" style="color:#ffb4b4;margin-top:10px"></div>
</div>
<div id="entries"></div>
<footer><div class="thin">Powered by Dreamcodes.NET</div></footer>
</div>
<script>
async function fetchEntries(){
    const resp = await fetch('?action=list');
    const data = await resp.json();
    const container = document.getElementById('entries');
    container.innerHTML='';
    data.forEach(e=>{
        const div=document.createElement('div');
        div.className='card entry';
        div.innerHTML=`<strong>${e.name}</strong><div class='entry-meta'>${e.created_at}</div><p>${e.message}</p><button onclick='deleteEntry(${e.id})' class='deleteBtn'>Löschen</button>`;
        container.appendChild(div);
    });
}

async function deleteEntry(id){
    if(!confirm('Eintrag wirklich löschen?')) return;
    const fd=new FormData(); fd.append('id',id);
    const resp=await fetch('?action=delete',{method:'POST',body:fd});
    const data=await resp.json();
    if(data.success) fetchEntries();
}

document.getElementById('submitBtn').addEventListener('click',async()=>{
    const fd=new FormData();
    fd.append('name',document.getElementById('name').value);
    fd.append('message',document.getElementById('message').value);
    fd.append('captcha',document.getElementById('captcha').value);
    const resp=await fetch('?action=add',{method:'POST',body:fd});
    const data=await resp.json();
    if(data.success){
        document.getElementById('name').value='';
        document.getElementById('message').value='';
        document.getElementById('captcha').value='';
        fetchEntries();
        document.getElementById('error').textContent='';
    }else{ document.getElementById('error').textContent=data.error||'Fehler' }
});

fetchEntries();
</script>
</body>
</html>
Vorheriges Tutorial
Nächstes Tutorial
Dreamcodes Redaktion
Dreamcodes Redaktion
Seit 1999 bewegt sich Dreamcodes in der Welt der digitalen Entwicklung, zwischen Codezeilen, Designentscheidungen und technischen Herausforderungen, die manchmal kleiner aussehen, als sie wirklich sind. Die Herausforderung besteht darin, komplexe Themen wie Webentwicklung, SEO, SEA, GEO, IT-Strukturen, Softwareentwicklung und moderne Technologien so aufzubereiten, dass sie verständlich, nachvollziehbar und vor allem praktisch nutzbar werden. Der Fokus liegt dabei darauf, Wissen nicht nur zu erklären, sondern es für reale Projekte anwendbar zu machen. Egal ob ein einfaches Script, ein umfangreicher Leitfaden oder ein tiefes technisches Tutorial: Das oberste Ziel dabei ist, dass Leser am Ende wirklich weiterkommen und ein Thema greifbarer wird als vorher. Über die Jahre gab es viele verschiedene Ansätze, Tools und Trends die kammen und auch wieder gingen. Genau das hilft neben Jahrelanger IT Erfahrung und mehrjähriger Tätigkeit im IT Bereich heute dabei, Inhalte mit Tiefe zu schreiben, die nicht nur Grundlagen vermitteln, sondern auch Hintergründe, Zusammenhänge und Best Practices erklären. Dreamcodes teilt diese Erfahrungen, mit dem Ziel, digitale Bildung für alle zugänglich zu machen, die neugierig sind, nach Lösungen suchen oder eigene digitale Projekte erfolgreich voranbringen möchten. Wenn dieses Wissen jemandem Zeit spart, ein Problem löst oder eine neue Idee auslöst, hat sich der Aufwand dahinter gelohnt. ;)

Vielleicht einen Blick wert