Gästebuch
Das gute alte Gästebuch, ein Klassiker im Internet. Auch wenn es durch Facebook & Co. immer stärker verdrängt wird, dient es als gute Übung für euch ein Gästebuch in PHP zu programmieren. Daran lernt ihr verschiedene Konzepte, beispielsweise wie man Daten abfragt, überprüft, in eine Datenbank speichert und auch wieder ausgibt.
Datenbanklayout
Für unser Gästebuch nutzen wir MySQL und PDO. Die Tabelle könnt ihr entweder mittels phpMyAdmin erstellen oder unten stehenden SQL-Code kopieren und ausführen. Unsere Datenbanktabelle wird dabei folgende Spalten beinhalten:
Hier der SQL-Code zur Erzeugung der Datenbanktabelle.
1 2 3 4 5 6 7 8 |
CREATE TABLE IF NOT EXISTS `gaestebuch` ( `id` int(10) unsigned NOT NULL, `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `text` text COLLATE utf8_unicode_ci NOT NULL, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `deleted_at` timestamp NULL DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; |
Die ersten vier Spalten sind hoffentlich selbst erklärend. Mit created_at speichern wir das Erstellungsdatum des Beitrags ab. Mittels der Spalte deleted_at realisieren wir einen sogenannten soft delete. Möchten wir später einen Beitrag im Gästebuch löschen, so muss dieser nicht tatsächlich und unwiderruflich gelöscht werden aus der Datenbank, sondern wir werden das Lösch-Datum setzen. Das Gästebuch wird dann nur Einträge ausgeben, die kein Löschdatum haben. Dadurch kann ein fälschlich gelöschter Artikel im Gästebuch leicht wiederhergestellt werden, indem wir das Löschdatum entfernen.
Abspeicherung von Beiträgen
Unser Gästebuch hat 3 Funktionalitäten: Wir benötigen ein Formular zur Eingabe, ein Script zum Abspeichern der Daten in der Datenbank und ein Script zum Ausgeben aller existenten Einträge. Das Formular zur Eingabe und die Ausgabe der existenten Beiträge schreiben wir in die gleichen Datei, in die gaestebuch.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Gästebuch</title> </head> <body> <?php $pdo = new PDO('mysql:host=localhost;dbname=php-einfach', 'root', ''); $show_form = true; $error = null; //Das Formular wurde abgesendet, überprüfe den Inhalt und speichere es ab if(isset($_GET['submit'])) { $name = trim($_POST['name']); $email = trim($_POST['email']); $text = trim($_POST['text']); //Überprüfen dass die E-Mail-Adresse gültig ist if(!filter_var($email, FILTER_VALIDATE_EMAIL)) { $error = 'Bitte eine gültige E-Mail-Adresse eingeben<br>'; } else if(empty($name)) { $error = 'Bitte einen Namen eingeben<br>'; } else if(empty($text)) { $error = 'Bitte einen Text eingeben<br>'; } else { $statement = $pdo->prepare("INSERT INTO gaestebuch (name, email, text) VALUES (:name, :email, :text)"); $result = $statement->execute(array('name' => $name, 'email' => $email, 'text' => $text)); if($result) { echo '<b>Dein Eintrag wurde erfolgreich gespeichert</b><br><br>'; $show_form = false; } else { $error = 'Beim Abspeichern ist leider ein Fehler aufgetreten<br>'; } } } ?> <?php if(!is_null($error)) { //Ein Fehler ist aufgetreten echo $error; } //Ausgabe des Formulars nur wenn $showForm == true ist if($show_form): ?> <form action="?submit=1" method="post"> Name:<br> <input type="text" size="40" maxlength="250" name="name"><br><br> E-Mail:<br> <input type="email" size="40" maxlength="250" name="email"><br><br> Text:<br> <textarea cols="50" rows="9" name="text"></textarea><br><br> <input type="submit" value="Eintragen"> </form> <?php endif; ?> <hr> <?php /*********************** * Ausgabe der Einträge ***********************/ //Ermittelt die Anzahl der Beiträge $statement = $pdo->prepare("SELECT COUNT(*) AS anzahl FROM gaestebuch WHERE deleted_at IS NULL"); $statement->execute(); $row = $statement->fetch(); $anzahl_eintrage = $row['anzahl']; echo "$anzahl_eintrage Personen sind eingetragen<br><br>"; //Berechne alles notwendige für die Blätterfunktion $seite = 1; if(isset($_GET['seite'])) { $seite = intval($_GET['seite']); } $beitraege_pro_seite = 20; $start = ($seite-1)*$beitraege_pro_seite; //Abfrage der Datenbank und Ausgabe der Daten $statement = $pdo->prepare("SELECT * FROM gaestebuch WHERE deleted_at IS NULL ORDER BY id DESC LIMIT :start, :limit"); $statement->bindParam(':start', $start, PDO::PARAM_INT); $statement->bindParam(':limit', $beitraege_pro_seite, PDO::PARAM_INT); $statement->execute(); while($row = $statement->fetch()) { $name = htmlentities($row['name']); $email = htmlentities($row['email']); $text = nl2br(htmlentities($row['text'])); $date = new DateTime($row['created_at']); $dateFormatted = $date->format('d.m.y H:i'); echo "<div style=\"border: 1px solid #000000;\"> <div style=\"border-bottom:1px solid #000000; padding: 5px; \">$dateFormatted von <a href=\"mailto:$email\">$name</a></div> <div style=\"padding: 5px;\">$text</div> </div><br>"; } //Berechne die Anzahl der Seiten: $anzahl_seiten = ceil($anzahl_eintrage / floatval($beitraege_pro_seite)); //Ausgabe der Seitenlinks: echo "<div align=\"center\">"; echo "<b>Seite:</b> "; //Ausgabe der Links zu den verschiedenen Seiten for($a=1; $a <= $anzahl_seiten; $a++) { //Wenn der User sich auf dieser Seite befindet, keinen Link ausgeben if($seite == $a){ echo " <b>$a</b> "; } else { //Aus dieser Seite ist der User nicht, also einen Link ausgeben echo " <a href=\"?seite=$a\">$a</a> "; } } echo "</div>"; ?> </body> </html> |
Die Ausgabe des Formulars befindet sich in den Zeilen 46 bis 61. Hier überprüfen wir zuerst ob das Formular überhaupt ausgegeben werden soll. Dies realisieren wir durch die Variable $show_form.
Dieses Formular wird an die selbe Seite abgeschickt und die Zeilen 14 bis 37 übernehmen die Abfrage der Daten und das Eintragen in die Datenbank. Zuerst werden alle Felder des Formulars abgefragt, danach werden diese Felder überprüft. Für das E-Mail-Feld wird mittels filter_var() überprüft, ob es eine gültige E-Mail-Adresse ist. Bei den anderen Feldern wird nur überprüft, dass diese nicht leer sind. Sollte ein Fehler auftreten, so wird eine Fehlermeldung in die Variable $error geschrieben. Sind alle Felder korrekt ausgefüllt, so wird in Zeile 27 - 28 ein INSERT in unsere Datenbank mittels prepared statement.
Die Ausgabe der Einträge und eine Blätterfunktion erfolgt ab Zeile 67. Zuerst wird die Anzahl der Einträge festgestellt und ausgegeben. Danach erfolgt der erste Teil unserer Blätterfunktion. Wir fragen die GET-Variable ab auf welcher Seite sich der Besucher befindet und berechnen dann die Information ab welchen Eintrag wir unsere Datenbank abfragen müssen. Die Formel dafür ist ($seite-1)*$beitraege_pro_seite.
Danach folgt der nächste Prepared Statement. Im SQL-Query schließen wir zuerst die Einträge aus, die ein Löschdatum besitzen (deleted_at IS NULL). Danach sortieren wir die Einträge so das wir den neuesten zuerst erhalten und für die Blätterfunktion bauen wir noch ein LIMIT ein (weitere Infos zu LIMIT und Prepared Statements).
Danach läuft das Script durch alle Einträge. Um Cross-Site-Scripting zu verhindern werden die Benutzereingaben mittels htmlentities() maskiert. Das Datum wandeln wir um in ein etwas leichter lesbares Format mittels DateFormat.
Zum Abschluss noch die Blätterfunktion. Um nicht eine endlos lange Seite mit tausenden von Einträgen im Gästebuch auszugeben, werden im obigen Script immer 20 Einträge pro Seite ausgeben. In Zeile 108 wird zuerst die Anzahl der benötigten Seiten berechnet. Danach folgt eine kleine for-Schleife, die entsprechende Links zu den einzelnen Seiten ausgibt. Einzige Ausnahme ist die Seite auf der sich der Besucher gerade findet, dort wird kein Link ausgeben.
Autor: Nils Reimers