Author: Progman, zuletzt bearbeitet von progman @ 2005/10/21 11:21:22
Bitte beachten Sie, dass die Tutorialkapitel zusammenhängen. Wenn sie direkt auf ein Kapitel verlinkt wurden müssen Sie gegebenenfalls die vorherigen Kapitel auch lesen. Achten Sie beim lesen darauf, dass Sie kein Kapitel überspringen.
Poll-Script
- Aufbau des Poll-Scripts
- MySQL-Tabellen zum Poll-Script
- Ändern des Layouts
- Adminbereich des Poll-Scripts
- Abstimmung hinzufügen
- Abstimmung bearbeiten
- Abstimmung löschen
- Formular zum Abstimmen
- Formularverarbeitung / Pollübersicht
1. Aufbau des Poll-Scripts
Jeder kennt es. Rechts ist meistens ein Bereich, in dem man voten kann. Dies ist bekannt als Poll. Wir schreiben nun auch so ein Poll-Script, wo man abstimmen kann und wo man in einer Übersicht alle schon abgeschlossenen Abstimmungen sieht. Damit das Abstimmungsergebnis nicht so sehr verfälscht werden kann wir eine IP- und Cookiesperre programmiert. Aber dies ist keine zuverlässige Methode, um eine Abstimmung eindeutig und nicht verfälscht zu halten. Denn ein Benutzer kann sich neu einwählen und/oder hat Cookies in seinem Browser deaktiviert. Eigentlich kann man Abstimmungen immer fälschen, es sei denn man muss sich irgentwo einloggen. Aber auch da kann man sich einen neuen Account machen und kann wieder voten.
2. MySQL-Tabellen zum Poll-Script
Nun müssen wir uns überlegen, wie wir die Daten in die MySQL-Datenbank speichern. Da man Frage, Antworten und Klicks speicher muss, würde man auf so ein Datenbank-Layout zuerst kommen.
poll(ID,Frage,Datum,Antwort1,Antwort2,Antwort3,....,Anzahl1,Anzahl2,Anzahl3,...) poll_ip(IP,Datum,PollID)
Doch die Tabelle poll entspricht nicht den erste 3 Normalformen. Nehmen wir an, wir haben soviele Spalten hinzugefügt, dass man 10 Antworten angeben kann. Doch was mache ich wenn ich mehr als 10 Antworten haben möchte? Oder was mache ich wenn ich weniger als 10 Antworten haben möchte. Ich könnte die Anzahl der Spalten mit den Antworten auf 50 oder so setzen, aber dann verbrauche ich zu viel Speicherplatz wenn ich ein Ja-Nein-Poll habe. Deswegen müssen wir die Tabellenstruktur in der Datenbank etwas ändern. Die Antworten speichern wir in eine extra Tabelle.
poll(ID,Frage,Datum) poll_antworten(ID,PollID,Antwort,Klicks) poll_ip(IP,Datum,PollID)
Jetzt können wir dynamisch die Anzahl der Antworten bestimmen. Wir müssen nur die Poll-ID der Abstimmungsfrage in die Tabelle der Antworten speichern, damit man weiß, welche Antwort zu welcher Frage gehört. Dieses Layout erleichtert auch das Rechnen des prozentualen Anteils einer Antwort. Im ersten Fall müsste man im SELECT Befehl eine riesige Addition errechnen lassen. Bei 50 Spalten ist das eine ganz schöne schreibarbeit.
Die Tabelle für die IPs ist genauso aufgebaut und entpsricht der Funktionsweise die der IP-Sperre der Newskommentare.
Wie man diese Tabellen nun in MySQL erstellt solltet ihr nun wissen. Dies nehme ich nun nicht mehr weiter durch.
3. Ändern des Layouts
In vielen Seiten sieht man dass Links das Menu, in der Mitte der Inhalt und Rechts solche sachen wie Poll oder Last-CW vorhanden ist. Diese Seiten haben ein 3 Spalten Layout. Doch wir haben im moment nur ein 2 Spalten Layout. Wir müssen deshalb das Layout etwas anpassen.
Das alte Design müssen wir nur um eine neue Spalte erweitern.
<?php
// ...
echo " <div id=\"root\">\n"; // ganz oberer Div-Holder
echo " <div id=\"banner\">\n"; // banner
include "banner.php";
echo " </div>\n";
echo " <div id=\"links\">\n"; // linkes Menu
include "menu.php";
echo " </div>\n";
echo " <div id=\"mitte\">\n"; // In der Mitte der Inhalt
include "inhalt.php";
echo " </div>\n";
echo " <br style=\"clear:both;\" />\n"; // css-float beenden
echo " </div>\n";
// ...
?>
Dies ändern wir nur ein klein wenig.
<?php
// ...
echo " <div id=\"root\">\n"; // ganz oberer Div-Holder
echo " <div id=\"banner\">\n"; // banner
include "banner.php";
echo " </div>\n";
echo " <div id=\"links\">\n"; // linkes Menu
include "menu.php";
echo " </div>\n";
echo " <div id=\"mitte\">\n"; // In der Mitte der Inhalt
include "inhalt.php";
echo " </div>\n";
echo " <div id=\"rechts\">\n"; // rechtes Menu
include "rechts.php";
echo " </div>\n";
echo " <br style=\"clear:both;\" />\n"; // css-float beenden
echo " </div>\n";
// ...
?>
In der Datei rechts.php includen wir nun unser Poll-Script.
<?php
//include "lastcw.php";
include "showpoll.php";
?>
In der showpoll.php erstellen wir erstmal nur ein Dummy-Code.
<?php
echo "<p>\n";
echo " Pollscript\n";
echo "</p>\n";
?>
Diese Datei zeigt dann entweder ein Formular zum abstimmen oder das momentane Ergebnis der Abstimmung an, falls schon abgestimmt wurde. Doch an dieses Script wenden wir uns später zu.
4. Adminbereich des Poll-Scripts
Das Poll-Script sollen wir wieder über den Adminbereich verwalten können. Dazu müssen wir ein paar Veränderungen an bestehenden Dateien vornehmen. In der Datei admin_menu.php müssen wir eine neue Zeile hinzufügen, die so ähnlich augebaut ist wie die anderen Zeilen. Als Wert für den GET-Parameter site wähle ich poll. Entsprechend müssen wir das Array $admin_site aus der Variablen-Konfigurationsdatei bearbeiten. Damit wir auch in den Poll-Bereich reinkönnen müssen wir auch noch das Array $allRights um ein neues Element Poll erweitern.
Nachdem wir dies alles gemacht haben, erstellen wir wieder unser Grundgerüst mit der add-edit-del-switch Abfrage wie bei den anderen Bereichen.
<?php
$rights = getRights();
if(!in_array("Admin", $rights)) {
no_rights();
} else {
switch(isset($_GET['action'])?$_GET['action']:'') {
case "add":
break;
case "edit":
break;
case "del":
break;
default:
echo "<p>\n";
echo " Bitte benutzen sie nur einen Link aus dem Adminmenu.\n";
echo "</p>\n";
back2admin();
break;
}
}
?>
Nun schreiben wir die Code-Teile zum hinzufügen, bearbeiten und löschen von Abstimmungen.
5. Abstimmung hinzufügen
Zuerst gucken wir allgemein ob schon eine Abstimmung läuft. Dies machen wir, indem wir prüfen, ob ein Poll innerhalb der letzen Woche hinzugefügt wurde. In der Datenbank wird in der Spalte Datum der Startpunkt der Abstimmung gespeichert. Der Query sieht dann so aus:
SELECT COUNT(*) AS Anzahl FROM poll WHERE DATE_ADD(Datum,INTERVAL 7 DAY) > NOW();
Diesen senden wir nun an die Datenbank. Dies machen wir nun mal mit unserer neu erstellten MySQL-Query Klasse, um ein wenig zu lernen wie man OOP benutzt.
<?php
case "add":
$sql = "SELECT
COUNT(*) AS Anzahl
FROM
poll
WHERE
DATE_ADD(Datum,INTERVAL 7 DAY) > NOW();";
$check = new Query($sql);
if($check->error()) {
die("<pre>".$check->geterror()."</pre>");
}
$row = $check->fetch();
if($row['Anzahl']) {
echo "<p class=\"error\">\n";
echo " Es läuft bereits eine Abstimmung, warten sie\n";
echo " bitte diese beendet ist.\n";
echo "</p>\n";
back2admin();
} else {
//es läuft keine Abstimmung
}
$check->free();
unset($check);
break;
?>
Wir erstellen nun erstmal wieder ein Grundlayout wie bei dem Newssystem. Die Antworten erstellen wir dann wieder mit einem extra Formular, genauso wie das Bearbeiten der Frage. Die Frage und die Antworten speichern wir in die Session.
<?php
case "add":
// ...
if($row['Anzahl']) {
// ...
} else {
if(!isset($_SESSION['Frage'])) {
$_SESSION['Frage'] = "";
}
if(!isset($_SESSION['Antworten'])) {
$_SESSION['Antworten'] = array();
}
switch(isset($_POST['submit'])?$_POST['submit']:'') {
default:
echo "<form action=\"index.php?section=admin&site=poll&action=add\"";
echo " method=\"post\"";
echo " class=\"formular\">\n";
echo " <p>\n";
echo " Neuen Poll hinzufügen\n";
echo " </p>\n";
echo " <ol>\n";
echo " <li>\n";
echo " Frage\n";
echo " <ul>\n";
echo " <li>\n";
echo $_SESSION['Frage']."\n";
echo " </li>\n";
echo " <li>\n";
echo "<input type=\"submit\" name=\"submit\" value=\"Frage bearbeiten\" />\n";
echo " </li>\n";
echo " </ul>\n";
echo " </li>\n";
echo " <li>\n";
echo " Antworten\n";
echo " <ul>\n";
if(count($_SESSION['Antworten'])) {
foreach($_SESSION['Antworten'] as $key => $value) {
echo "<li>\n";
echo "<input type=\"chechbox\" ";
echo " name=\"antworten[]\" ";
echo " value=\"".$key."\" />\n";
echo $value."\n";
echo "</li>\n";
}
}
echo " <li>\n";
echo "<input type=\"submit\" name=\"submit\"";
echo " value=\"Neue Antwort hinzufügen\" />\n";
if(count($_SESSION['Antworten'])) {
echo "<input type=\"submit\" name=\"submit\"";
echo " value=\"Löschen\" />\n";
}
echo " </li>\n";
echo " </ul>\n";
echo " </li>\n";
echo " <li>\n";
echo "<input type=\"submit\" name=\"submit\" value=\"Poll hinzufügen\" />\n";
echo "<input type=\"reset\" name=\"submit\" value=\"Zurücksetzen\" />\n";
echo "<input type=\"hidden\" name=\"".session_name()."\"";
echo " value=\"".session_id()."\" />";
echo " </li>\n";
echo " <ol>\n";
echo "</form>\n";
break;
}
}
$check->free();
unset($check);
break;
?>
Nun erstellen wir die Scripte zum Bearbeiten der Frage und zum Hinzufügen neuer Antworten.
<?php
case 'Frage bearbeiten':
echo "<form action=\"index.php?section=admin&site=poll&action=add\" ";
echo " method=\"post\"";
echo " class=\"formular\">\n";
echo " <p>\n";
echo " Frage bearbeiten.\n";
echo " </p>\n";
echo " <ol>\n";
echo " <li>\n";
echo " <label for=\"frage\">Frage</label>\n";
echo " <input type=\"text\" name=\"frage\"";
echo " id=\"name\" value=\"".$_SESSION['Frage']."\" />\n";
echo " </li>\n";
echo " <li>\n";
echo " <input type=\"submit\" name=\"submit\"";
echo " value=\"Frage speichern\" />\n";
echo " <input type=\"hidden\" name=\"".session_name()."\"";
echo " value=\"".session_id()."\" />";
echo " </li>\n";
echo " </ol>\n";
echo "</form>\n";
back2admin();
break;
?>
Und dann noch die Antworten.
<?php
case 'Neue Antwort hinzufügen':
echo "<form action=\"index.php?section=admin&site=poll&action=add\" ";
echo " method=\"post\"";
echo " class=\"formular\">\n";
echo " <p>\n";
echo " Antwort hinzufügen\n";
echo " </p>\n";
echo " <ol>\n";
echo " <li>\n";
echo " <label for=\"antwort\">Antwort</label>\n";
echo " <input type=\"text\" name=\"antwort\"";
echo " id=\"antwort\" />\n";
echo " </li>\n";
echo " <li>\n";
echo " <input type=\"submit\" name=\"submit\"";
echo " value=\"Antwort hinzufügen\" />\n";
echo " <input type=\"hidden\" name=\"".session_name()."\"";
echo " value=\"".session_id()."\" />";
echo " </li>\n";
echo " </ol>\n";
echo "</form>\n";
break;
?>
Die anderen Programmcodeteile fügen wir nun in den default-Teil ein, da sofort das Hauptformular angezeigt werden soll.
<?php
default:
if(isset($_POST['submit']) AND "Frage speichern" == $_POST['submit']) {
$_SESSION['Frage'] = htmlspecialchars(trim($_POST['frage']))
}
if(isset($_POST['submit']) AND "Antwort hinzufügen" == $_POST['submit']) {
$_SESSION['Antworten'][] = htmlspecialchars(trim($_POST['antwort']));
}
// ... Hauptformular
// ...
break;
?>
Nachdem man Antworten hinzugefügt hat, kann man diese Antworten auch wieder löschen. Dazu wählt man sie aus und klick auf den Button Löschen. Der dazu zuständige Programmcode schreiben wir auch im default-Bereich.
<?php
default:
if(isset($_POST['submit']) AND "Frage speichern" == $_POST['submit']) {
$_SESSION['Frage'] = htmlspecialchars(trim($_POST['frage']))
}
if(isset($_POST['submit']) AND "Antwort hinzufügen" == $_POST['submit']) {
$_SESSION['Antworten'][] = htmlspecialchars(trim($_POST['antwort']));
}
if(isset($_POST['submit']) AND "Löschen" == $_POST['submit']) {
if(isset($_POST['antworten'])) {
foreach($_POST['antworten'] as $value) {
unset($_SESSION['Antworten'][$value]);
}
$_SESSION['Antworten'] = array_values($_SESSION['Antworten']);
// lücken im Array schließen.
}
}
// ... Hauptformular
// ...
break;
?>
Nun brauchen wir nur noch den Programmteil, der den Poll auch wirklich in die Datenbank einträgt. Wir packen diesen Teil auch in den defaul-Bereich, da es sein kann, dass wir das Formular nochmal anzeigen müssen.
<?php
default:
if(isset($_POST['submit']) AND "Frage speichern" == $_POST['submit']) {
$_SESSION['Frage'] = htmlspecialchars(trim($_POST['frage']))
}
if(isset($_POST['submit']) AND "Antwort hinzufügen" == $_POST['submit']) {
$_SESSION['Antworten'][] = htmlspecialchars(trim($_POST['antwort']));
}
if(isset($_POST['submit']) AND "Löschen" == $_POST['submit']) {
if(isset($_POST['antworten'])) {
foreach($_POST['antworten'] as $value) {
unset($_SESSION['Antworten'][$value]);
}
$_SESSION['Antworten'] = array_values($_SESSION['Antworten']);
// lücken im Array schließen.
}
}
if(isset($_POST['submit']) AND "Poll hinzufügen" == $_POST['submit']) {
if(count($_SESSION['Antworten']) >= 2) {
$sql = "INSERT INTO
poll(Frage,Datum)
VALUES
('".addslashes($_SESSION['Frage'])."',
NOW());";
$poll = new Query($sql);
if($poll->error()) {
die("<pre>".$poll->getError()."</pre>\n");
}
unset($poll);
// nun muss ich die ID holen, damit ich die
// antworten hinzufügen kann
$sql = "SELECT
ID
FROM
poll
ORDER BY
Datum DESC
LIMIT
1;";
$getid = new Query($sql);
if($getid->error()) {
die("<pre>".$getid->getError()."</pre>\n");
}
$row = $getid->fetch();
$PollID = $row['ID'];
$getid->free();
unset($getid);
// und nun die Antworten hinzufügen, und die Klickcounter
// auf 0 setzen.
foreach($_SESSION['Antworten'] as $antwort) {
$sql = "INSERT INTO
poll_antworten(PollID,Antwort,Klicks)
VALUES
('".$PollID."',
'".$antwort."',
'0');";
$ansqry = new Query($sql);
if($ansqry->error()) {
die("<pre>".$ansqry->getError()."</pre>\n");
}
unset($ansqry);
}
echo "<p>\n";
echo " Poll wurde hinzugefügt.\n";
echo "</p>\n";
back2admin();
break;
// wir wollen nicht die If-Abfrage verlassen, was ja gar nicht
// geht, sondern die switch-Abfrage, da wir das Hauptformular
// nicht mehr brauchen.
} else {
echo "<p>\n";
echo " Bitte fügen sie mindestesn 2 Antworten hinzu.";
echo "</p>\n";
}
}
// ... Hauptformular
// ...
break;
?>
6. Abstimmung bearbeiten
Beim Bearbeiten einer Abstimmung müssen wir auf einige Sachen aufpassen. Wir können nicht einfach, wie bei den News die related Links, alle Antworten löschen und die bearbeiteten hinzufügen. Denn dann sind ja unsere Abstimmungen verloren. Das ist auch der Grund, warum die Tabelle poll_antworten auch eine ID-Spalte hat. Mit der können wir eine Antwort genau identifizieren bzw. erreichen.
Zuerst schreiben wir ein Formular um die Abstimmung zu wählen, die man bearbeiten möchte.
<?php
case "edit":
if(!isset($_SESSION['ID'])) {
$_SESSION['ID'] = 0;
} switch(@$_POST['submit']) {
case "Poll auswählen":
if(isset($_POST['PollID']) AND $_POST['PollID']) {
$sql = "SELECT
COUNT(*) as Anzahl
FROM
poll
WHERE
ID = '".addslashes($_POST['PollID'])."';";
$check = new Query($sql);
if($check->error()) {
die("<pre>".$check-getError()."</pre>\n");
}
$row = $check->fetch();
if($row['Anzahl']) {
$_SESSION['ID'] = $_POST['PollID'];
} else {
echo "<p>\n";
echo " Bitte wählen sie einen gültigen Poll aus.\n";
echo "</p>\n";
}
} else {
echo "<p>\n";
echo " Bitte wählen sie einen Poll aus\n";
echo "</pre>\n";
}
default:
if($_SESSION['ID']) {
// Zeige Formular
} else {
echo "<form action=\"index.php?section=admin&site=poll&action=edit\"";
echo " method=\"post\"";
echo " class=\"formular\">\n";
echo " <p>\n";
echo " </p>\n";
echo " Abstimmung auswählen.\n";
echo " <p>\n";
echo " <ol>n";
echo " <li>\n";
echo " <label for=\"pollid\">Poll</label>\n";
$sql = "SELECT
ID,
Frage,
Datum
FROM
poll
ORDER BY
Datum DESC;";
$polls = new Query($sql);
if($polls->error()) {
die("<pre>".$polls->getError()."</pre>\n");
}
echo "<select id=\"pollid\" name=\"PollID\">\n";
echo " <option value=\"0\">Bitte einen Poll wählen</option>\n";
while($row = $polls->fetch()) {
echo " <option value=\"".$row['ID']."\">\n";
echo $row['Frage']."(".$row['Datum'].")\n";
echo " </option\n";
}
echo "</select>\n";
echo " </li>\n";
echo " <li>\n";
echo " <input type=\"submit\"";
echo " name=\"submit\"";
echo " value=\"Poll auswählen\" />\n";
echo " <input type=\"reset\"";
echo " name=\"submit\"";
echo " value=\"Zurücksetzen\" />\n";
echo " <input type=\"hidden\"";
echo " name=\"".session_name()."\"";
echo " value=\"".session_id()."\" />\n";
// Wegen dem Tutorial umgebrochen
echo " </li>\n";
echo " </ol>\n";
echo "</form>\n";
}
break;
}
break;
?>
Nun erstellen wir das Formular zum bearbeiten. Um die Abstimmung nicht zu verfälschen, darf man nur Antworten bearbeiten. Diese Funktion sollte man auch nur nutzen, um ein Schreibfehler zu beheben.
<?php
if($_SESSION['ID']) {
$sql = "SELECT
Frage
FROM
poll
WHERE
ID = '".$_SESSION['ID']."';";
$daten = new Query($sql);
if($daten->error()) {
die("<pre>".$daten->getError()."</pre>\n");
}
$row = $daten->fetch();
$daten->free();
unset($daten);
$frage = $row['Frage'];
// Die Frage zum Poll geholt.
$sql = "SELECT
ID,
Antwort
FROM
poll_antworten
WHERE
PollID = '".$_SESSION['ID']."';";
$ansqry = new Query($sql);
if($ansqry->error()) {
die("<pre>".$ansqry->getError()."</pre>\n");
}
$antworten = array();
while($row = $ansqry->fetch()) {
$antworten[$row['ID']] = $row['Antwort'];
}
$ansqry->free();
unset($ansqry);
// Alle antworten geholt
echo "<form action=\"index.php?section=admin&site=poll&action=edit\"";
echo " method=\"post\"";
echo " class=\"formular\">\n";
echo " <p>\n";
echo " Abstimmung bearbeiten\n";
echo " </p>\n";
echo " <ol>\n";
echo " <li>\n";
echo " <label for="frage">Frage</label>\n";
echo " <input type=\"text\" name=\"Frage\"";
echo " id=\"frage\" value=\"".$frage."\"/>\n";
echo " </li>\n";
echo " <li>\n";
echo " Antworten\n";
echo " <ol>\n";
foreach($antworten as $key => $value) {
echo " <li>\n";
echo " <label for=\"Antwort_".$key."\">\n";
echo " Antwort\n";
echo " </label>\n";
echo " <input type=\"text\" name=\"Antwort[".$key."]\"";
echo " value=\"".$value."\" id=\"Antwort_".$key."\" />\n";
echo " </li>\n";
}
echo " </ol>\n";
echo " </li>\n";
echo " <li>\n";
echo "<input type=\"submit\" name=\"submit\" value=\"Änderungen abspeichern\" />\n";
echo "<input type=\"reset\" name=\"submit\" value=\"Zurücksetzen\" />\n";
echo "<input type=\"hidden\" name=\"".session_name()."\" value=\"".session_id()."\" />\n";
echo " </li>\n";
echo " </ol>\n";
echo "</form>\n";
back2admin();
}
?>
Nun brauchen wir den Programmcode, der die Frage und die Antworten in die Datenbank speichert.
<?php
case 'Änderungen abspeichern':
if($_SESSION['ID']) {
// Sicher ist sicher
// als erstes speichern wir die Frage.
$sql = "UPDATE
poll
SET
Frage = '".addslashes($_POST['Frage'])."'
WHERE
ID = '".$_SESSION['ID']."';";
$updfrg = new Query($sql);
if($updfrg->error()) {
die("<pre>".$updfrg->getError()."</pre>\n");
}
unset($updfrg);
// nun die AntwortAen
foreach($_POST['Antworten'] as $key => $value) {
$sql = "UPDATE
poll_antworten
SET
Antwort = '".addslashes($value)."'
WHERE
ID = '".$key."' AND
PollID = '".$_SESSION['ID']."';";
$updant = new Query($sql);
if($updant->error()) {
die("<pre>".$updant->getError()."</pre>\n");
}
unset($updant);
}
echo "<p>\n";
echo " Die Änderungen wurden gespeichert.";
echo "</p>\n";
} else {
echo "<p>\n";
echo " Bitte benutzen sie ein Formular aus dem Adminbereich.\n";
echo "</p>\n";
}
break;
?>
Wenn man einen Poll etwas genau bearbeiten möchte, z.B. eine neue Antwort hinzufügen, muss man dies über PHPMyAdmin machen. Dadurch kann aber die Abstimmung verfälscht werden.
7. Abstimmung löschen
Das Löschen einer Abstimmung ist sehr einfach, da brauchen wir nur ein paar If-Abfragen.
<?php
case 'del':
if(isset($_POST['submit']) AND "Poll löschen" == $_POST['submit']) {
if($_POST['PollID']) {
$sql = "DELETE FROM
poll_antworten
WHERE
PollID = '".$_POST['PollID']."';";
$delant = new Query($sql);
if($delant->error()) {
die("<pre>".$delant->getError()."</pre>\n");
}
unset($delant);
$sql = "DELETE FROM
poll
WHERE
ID = '".$_POST['PollID']."';";
$delfrg = new Query($sql);
if($delfrg->error()) {
die("<pre>".$delfrg->getError()."</pre>\n");
}
unset($delfrg);
echo "<p>\n";
echo " Der Poll wurde gelöscht\n";
echo "</p>\n";
back2admin();
} else {
echo "<p>\n";
echo " Bitte wählen sie einen gültigen Poll aus.\n";
echo "</p>\n";
back2admin();
}
} else {
echo "<form action=\"index.php?section=admin&site=poll&action=del\"";
echo " method=\"post\"";
echo " class=\"formular\">\n";
echo " <p>\n";
echo " Abstimmung löschen.\n";
echo " </p>\n";
echo " <ol>\n";
echo " <li>\n";
echo " <label for=\"pollid\">Poll</label>\n";
$sql = "SELECT
ID,
Frage,
Datum
FROM
poll
ORDER BY
Datum DESC;";
$polls = new Query($sql);
if($polls->error()) {
die("<pre>".$polls->getError()."</pre>\n");
}
echo "<select id=\"pollid\" name=\"PollID\">\n";
echo " <option value=\"0\">Bitte einen Poll wählen</option>\n";
while($row = $polls->fetch()) {
echo " <option value=\"".$row['ID']."\">\n";
echo $row['Frage']."(".$row['Datum'].")\n";
echo " </option\n";
}
echo "</select>\n";
echo " </li>\n";
echo " <li>\n";
echo " <input type=\"submit\"";
echo " name=\"submit\"";
echo " value=\"Poll löschen\" />\n";
echo " <input type=\"reset\"";
echo " name=\"submit\"";
echo " value=\"Zurücksetzen\" />\n";
echo " <input type=\"hidden\"";
echo " name=\"".session_name()."\"";
echo " value=\"".session_id()."\" />\n";
echo " </li>\n";
echo " </ol>\n";
echo "</form>\n";
}
break;
?>
Ein einfaches Auswählen und die Frage und Antworten werden gelöscht.
8. Formular zum Abstimmen
Nun schreiben wir das Script, indem der User seine Abstimmung wählen kann. Dies machen wir in der Datei showpoll.php. Wenn der User noch nicht abgestimmt hat, wird dort ein Formular erstellt. Falls er bereits abgestimmt hat, wird an dieser Stelle nur das Ergebnis angezeigt. Anhand der IP-Sperre und einem ggf. gesetzen Cookies erkennen wir, ob der User schon abgestimmt hat oder nicht.
Erstmal gucken wir, ob überhaupt ein Poll läuft oder ob der Poll schon beendet ist.
<?php
$sql = "SELECT
ID,
DATE_FORMAT(Datum,'".DATE_STYLE."') as Start,
Frage,
DATE_FORMAT(DATE_ADD(Datum, INTERVAL 7 Day),'".DATE_STYLE."') as Stop,
NOW() BETWEEN
Datum AND
DATE_ADD(Datum, INTERVAL 7 Day) as Laeuft
FROM
poll
ORDER BY
Datum DESC
LIMIT
1;";
$pollqry = new Query($sql);
if($pollqry->error()) {
die("<pre>".$pollqry->getError()."</pre>\n");
}
if($polldaten = $pollqry->fetch()) {
// es ist ein Poll vorhanden
} else {
echo "<p>\n";
echo " Kein Poll vorhanden\n";
echo "</p>\n";
}
$pollqry->free();
unset($pollqry);
?>
Wenn ein Datensatz aus der Tabelle geholt werden konnte, ist auch ein Poll vorhanden und wird dann entsprechend angezeigt. Wir gucken nun ob der User schon gevotet hat. BETWEEN guckt nach ob ein Wert zwischen 2 Werten liegt und liefert entsprechend 1 oder 0 zurück. Die Syntax von BETWEEN kann man auf http://www.mysql.de/ nachlesen.
<?php
// ...
if($polldaten = $pollqry->fetch()) {
// gucken ob der User in der DB ist
$sql = "SELECT
COUNT(*) as Anzahl
FROM
poll_ip
WHERE
IP = '".$_SERVER['REMOTE_ADDR']."' AND
PollID = '".$polldaten['ID']."';";
$ipqry = new Query($sql);
if($ipqry->error()) {
die("<pre>".$ipqry->getError()."</pre>\n");
}
$tmp = $ipqry->fetch();
$voted = $tmp['Anzahl'];
$ipqry->free();
unset($ipqry);
if(isset($_COOKIE['voted']) AND $_COOKIE['voted'] == $polldaten['ID']) {
$voted++;
}
if($voted OR !$polldaten['Laeuft']) {
// Wenn er schon gevoted hat oder der Poll ist schon
// abgeschlossen soll nur das Ergebnis ngezeigt werden.
} else {
// Zeige Formular zum Abstimmen
}
}
// ...
?>
Nun schreiben wir das Formular. Dieses Formular besteht aus Radioboxen mit denen der User seine Antwort auswählen kann. Dieses Formular wir an eine extra Seite geschickt.
<?php
if($voted OR !$polldaten['Laeuft']) {
// ...
} else {
echo "<form action=\"index.php?section=poll&action=vote\"";
echo " method=\"post\"";
echo " class=\"poll\">\n";
echo " <p>\n";
echo changetext($polldaten['Frage'])."\n";
echo " </p>\n";
$sql = "SELECT
Antwort,
ID
FROM
poll_antworten
WHERE
PollID = '".$polldaten['ID']."';";
$ansqry = new Query($sql);
if($ansqry->error()) {
echo "<p>\n";
echo $ansqry->getError();
echo "</p>\n";
die();
}
echo " <ul>\n";
while($row = $ansqry->fetch()) {
echo "<li>\n";
echo " <label for=\"ans".$row['ID']."\">\n";
echo changetext($row['Antwort']);
echo " </label>\n";
echo " <input type=\"radio\" name=\"antwort\" ";
echo " value=\"".$row['ID']."\" id=\"ans".$row['ID']."\" />\n";
echo "</li>\n";
}
echo " </ul>\n";
echo " Start: ".$polldaten['Start']."<br />\n";
echo " Ende: ".$polldaten['Stop']."<br />\n";
echo "<input type=\"submit\" name=\"submit\" value=\"Abstimmen\" />\n";
echo "<input type=\"reset\" name=\"submit\" value=\"Zurücksetzen\" />\n";
echo "<input type=\"hidden\" name=\"PollID\" value=\"".$polldaten['ID']."\" />\n";
echo "</form>\n";
}
?>
Die Verarbeitung des Formulars schreiben wir später. Nun kommt der Teil wo das Ergebnis der Abstimmung angezeigt wird.
<?php
if($voted OR !$polldaten['Laeuft']) {
echo "<table class=\"poll\">";
echo " <p>\n";
echo " ".changetext($polldaten['Frage'])."\n";
echo " </p>\n";
$sql = "SELECT
Antwort
Klicks
FROM
poll_antworten
WHERE
PollID = '".$polldaten['ID']."';";
$ansqry = new Query($sql);
if($ansqry->error()) {
echo " <pre>\n";
echo $ansqry->getError();
echo " </pre>\n";
die();
}
$sql = "SELECT
SUM(Klicks) as Anzahl
FROM
poll_antworten
WHERE
PollID = '".$polldaten['ID']."';";
$maxqry = new Query($sql);
if($maxqry->error()) {
echo " <pre>\n";
echo $ansqry->getError();
echo " </pre>\n";
die();
}
$maxrow = $maxqry->fetch();
$maxqry->free();
unset($maxqry);
$Anzahl = $maxrow['Anzahl'];
echo " <ol>\n";
while($row = $ansqry->fetch()) {
echo "<li>\n";
echo $row['Antwort'];
if($Anzahl) {
$prozent = $row['Klicks'] / $Anzahl * 100;
$prozent = round($prozent);
echo $prozent."% (".$row['Klicks'].")";
} else {
echo "0% (0)";
}
echo "</li>\n";
}
echo " Start: ".$polldaten['Start']."<br />\n";
echo " Ende: ".$polldaten['Stop']."\n";
if($voted) {
echo "<br />Sie haben schon gevoted\n";
}
echo "</table>\n";
} else {
// ...
}
?>
Die If-Abfrage mit dem $Anzahl müssen wir machen, damit er nicht meckert, das er nicht durch 0 teilen kann. Denn es kann sein, dass noch keiner abgestimmt hat. Dann ist die Summer der Klicks 0, und der prozentuale Anteil kann nicht errechnet werden.
Probleme gibt es beim Runden. Hier wird nur auf eine ganze Zahl ohne Nachkommastellen gerundet. Nehmen wir aber mal an, wir haben 2 Ergebnisse 49.5 und 50.5. Nach dem Abrunden würde dann folgendes Ergebnis rauskommen: 50 und 51. Damit kommen wir auf einen Gesamtergebnis von 101 Prozent. Dies muss man irgendwie abfangen. Man könnte z.B. von einer Zahl 100 immer die aktuelle Prozentanzahl abziehen und bei der letzten Antwort gibt man den Rest der Zahl aus (100-51=49). Aber solange es der Besucher der Seite nicht merk ist es ja egal ;).
9. Formularverarbeitung / Pollübersicht
Das Formular für das Voten wird an index.php?section=poll&action=vote gesendet. Dies heißt, dass wir (mal wieder ;)) das Array $dateien erweitern müssen. Dabei soll eine Datei poll.php geöffnet werden. Diese Datei soll nicht nur das Formular verarbeiten sondern auch eine Übersicht der schon abgeschlossenen Abstimmungen zeigen. Mit einen Klick sieht man dann genauere Informationen über die Abstimmung. Was er nun machen soll unterscheiden wir anhand der GET-Angabe action.
<?php
switch(isset($_GET['action'])?$_GET['action']:'')
{
case 'vote':
break;
case 'details':
break;
default:
break;
}
?>
In dem vote-Teil speichern wir nun die gewählte Abstimmung in der Datenbank ab. Wir brauchen aber noch ein paar If-Abfragen, die dafür sort, dass die Abstimmung auch nur unter bestimmten Umständen gespeichert wird.
<?php
case 'vote':
$sql = "SELECT
ID,
DATE_FORMAT(Datum,'".DATE_STYLE."') as Start,
Frage,
DATE_FORMAT(DATE_ADD(Datum, INTERVAL 7 Day),'".DATE_STYLE."') as Stop,
NOW() BETWEEN
Datum AND
DATE_ADD(Datum, INTERVAL 7 Day) as Laeuft
FROM
poll
ORDER BY
Datum DESC
LIMIT
1;";
$pollqry = new Query($sql);
if($pollqry->error()) {
die("<pre>".$pollqry->getError()."</pre>\n");
}
if($polldaten = $pollqry->fetch()) {
// es ist ein Poll vorhanden
$sql = "SELECT
COUNT(*) as Anzahl
FROM
poll_ip
WHERE
IP = '".$_SERVER['REMOTE_ADDR']."' AND
PollID = '".$polldaten['ID']."';";
$ipqry = new Query($sql);
if($ipqry->error()) {
die("<pre>".$ipqry->getError()."</pre>\n");
}
$tmp = $ipqry->fetch();
$voted = $tmp['Anzahl'];
$ipqry->free();
unset($ipqry);
if(isset($_COOKIE['voted']) AND $_COOKIE['voted'] == $polldaten['ID']) {
$voted++;
}
if($voted) {
echo "<p>\n";
echo " Sie haben schon für diese Abstimmung gevotet.\n";
echo " Sie können nicht nochmal voten\n";
echo "</p>\n";
} else {
if($polldaten['Laeuft']) {
$sql = "UPDATE
poll_antworten
SET
Klicks = Klicks + 1
WHERE
ID = '".$_POST['antwort']."' AND
PollID = '".$polldaten['ID']."';";
// Die PollID muss mit in die Bedingung, da man
// sonst beliebige Antworten erhöhen kann.
$ansqry = new Query($sql);
if($ansqry->error()) {
die("<pre>".$ansqry->getError()."</pre>\n");
}
if($ansqry->numRows()) {
// Es wurde ein Datensatz ubgedatet
$sql = "INSERT INTO
poll_ip(IP,Datum,PollID)
VALUES
('".$_SERVER['REMOTE_ADDR']."',
NOW(),
'".$polldaten['ID']."');";
$ipqry = new Query($sql);
if($ipqry->error()) {
die("<pre>".$ipqry->getError()."</pre>\n");
}
unset($ipqry);
echo "<p>";
echo " Ihre Abstimmung wurde gespeicher.\n";
echo "</p>\n";
} else {
echo "<p>\n";
echo " Bitte Benutzen sie eine Auswahl aus dem Poll\n";
echo " Formular.\n";
echo "</p>\n";
}
} else {
echo "<p>\n";
echo " Der letzte hinzugefügene Poll ist bereits beendet.\n";
echo " Sie können für diesen Poll nicht mehr abstimmen.\n";
echo "</p>\n";
}
}
} else {
echo "<p>\n";
echo " Kein Poll zum Abstimmen vorhanden\n";
echo "</p>\n";
}
$pollqry->free();
unset($pollqry);
break;
?>
So weit, so gut. Doch was machen wir mit den Cookie? Den Cookie müssen wir, wenn überhaupt, oben setzen. Aber die Verarbeitung des Scriptes ist unten. Wir müssen nun wieder die index.php bearbeiten und dort eine neue Datei includen. Diese Datei nenne ich cookie.php um anzudeuten, dass diese Datei für Cookies zuständig ist.
<?php
error_reporting(E_ALL);
include "inc/config.php"; // die Konfigurationsdateien lesen.
@mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS) OR die(mysql_error());
mysql_select_db(MYSQL_DATABASE) OR die(mysql_error());
// Session starten wenn ?section=admin geöffnet wurde
if(isset($_GET['section']) AND ("admin" == $_GET['section'])) {
session_start();
if(!isset($_SESSION['IP'])) {
$_SESSION['IP'] = $_SERVER['REMOTE_ADDR'];
}
if($_SESSION['IP'] != $_SERVER['REMOTE_ADDR']) {
echo "<p>\n";
echo " Sie dürfen nicht die Session von einem\n";
echo " anderen user Benutzten. Bitte benutzen sie\n";
echo " folgenden Link um zur Homepage zu gelangen.\n";
echo " <a href=\"/\">Zurück zur Homepage</a>\n";
echo "</p>\n";
die(); // Aus Sicherheitsgründen die Abarbeitung sofort beenden
}
}
if(get_magic_quotes_gpc()) {
array_stripslashes($_GET);
array_stripslashes($_POST);
array_stripslashes($_COOKIE);
}
include "cookie.php"; // Cookie-Relevante Daten laden
echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n";
echo " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
// ...
?>
Die cookie.php sieht so aus.
<?php
if(isset($_GET['section'], $_GET['action'],
$_POST['PollID'], $_POST['antwort']) AND
"poll" == $_GET['section'] AND "vote" == $_GET['action'] AND
$_POST['PollID'] AND $_POST['antwort']) {
// Diesen Bereich nur erreichen, wenn die entsprechenden
// Variablen vorhanden und gültig sind.
$sql = "SELECT
ID,
DATE_FORMAT(Datum,'".DATE_STYLE."') as Start,
Frage,
DATE_FORMAT(DATE_ADD(Datum, INTERVAL 7 Day),'".DATE_STYLE."') as Stop,
NOW() BETWEEN
Datum AND
DATE_ADD(Datum, INTERVAL 7 Day) as Laeuft
FROM
poll
ORDER BY
Datum DESC
LIMIT
1;";
$pollqry = new Query($sql);
if($pollqry->error()) {
die("<pre>".$pollqry->getError()."</pre>\n");
}
if($polldaten = $pollqry->fetch()) {
// es ist ein Poll vorhanden
$sql = "SELECT
COUNT(*) as Anzahl
FROM
poll_ip
WHERE
IP = '".$_SERVER['REMOTE_ADDR']."' AND
PollID = '".$polldaten['ID']."';";
$ipqry = new Query($sql);
if($ipqry->error()) {
die("<pre>".$ipqry->getError()."</pre>\n");
}
$tmp = $ipqry->fetch();
$voted = $tmp['Anzahl'];
$ipqry->free();
unset($ipqry);
if(isset($_COOKIE['voted']) AND $_COOKIE['voted'] == $polldaten['ID']) {
$voted++;
}
if(!$voted) {
if($polldaten['Laeuft']) {
$sql = "SELECT
COUNT(*) as Anzahl
FROM
poll_antworten
WHERE
ID = '".$_POST['antwort']."' AND
PollID = '".$polldaten['ID']."';";
// Die PollID muss mit in die Bedingung, da man
// sonst beliebige Antworten erhöhen kann.
$ansqry = new Query($sql);
if($ansqry->error()) {
die("<pre>".$ansqry->getError()."</pre>\n");
}
$tmp = $ansqry->fetch();
if($tmp['Anzahl']) {
// Alle Daten stimmen, Cookie senden
setcookie("voted", $polldaten['ID'], time()+(60*60*24*7));
}
}
}
}
$pollqry->free();
unset($pollqry);
}
?>
Der Code sieht so ähnlich aus, wie der davor. Ist ja auch logisch denn wir müssen ja die selben Überprüfungen machen. Das einzigste was anders ist sind die fehlenden Echo-Befehle und der UPDATE Befehl wurde durch ein SELECT-Befehl + setcookie ersetzt.
Damit nicht zufällig ein falscher User nicht voten kann wird eine IP in der Datenbank nach 24 Stunden gelöscht. Den SQL-Befehl fügen wir bei dem Pollformular/ergebnis ein.
<?php
$sql = "SELECT
ID,
DATE_FORMAT(Datum,'".DATE_STYLE."') as Start,
Frage,
DATE_FORMAT(DATE_ADD(Datum, INTERVAL 7 Day),'".DATE_STYLE."') as Stop,
NOW() BETWEEN
Datum AND
DATE_ADD(Datum, INTERVAL 7 Day) as Laeuft
FROM
poll
ORDER BY
Datum DESC
LIMIT
1;";
$pollqry = new Query($sql);
if($pollqry->error()) {
die("<pre>".$pollqry->getError()."</pre>\n");
}
if($polldaten = $pollqry->fetch()) {
// ...
} else {
echo "<p>\n";
echo " Kein Poll vorhanden\n";
echo "</p>\n";
}
$pollqry->free();
unset($pollqry);
$sql = "DELETE FROM
poll_ip
WHERE
Datum < DATE_SUB(NOW(), INTERVAL 1 DAY);";
$delqry = new Query($sql);
if($delqry->error()) {
die("<pre>".$delqry->getError()."</pre>\n");
}
unset($delqry);
?>
Nun schreiben wir noch die Pollübersicht. Diese erreicht man wenn man nur index.php?section=poll öffnen, also der GET-Parameter action leer ist.
<?php
default:
echo "<div class=\"polls\">\n";
echo " <p>\n";
echo " Übersicht der Abstimmungen\n";
echo " </p>\n";
$sql = "SELECT
ID,
DATE_FORMAT(Datum,'".DATE_STYLE."') as Start,
Frage,
DATE_FORMAT(DATE_ADD(Datum, INTERVAL 7 Day),'".DATE_STYLE."') as Stop,
NOW() BETWEEN
Datum AND
DATE_ADD(Datum, INTERVAL 7 Day) as Laeuft
FROM
poll
ORDER BY
Datum DESC";
$pollqry = new Query($sql);
if($pollqry->error()) {
die("<pre>".$pollqry->getError()."</pre>\n");
}
if($Anzahl = $pollqry->numRows()) {
echo "<ul>\n";
while($row = $pollqry->fetch()) {
echo "<li>\n";
echo "<a href=\"index.php?section=poll&action=details&PollID=".$row['ID']."\">\n";
// Ausgerückt, damit das Tutorial nicht so breit wird
echo changetext($row['Frage']);
echo "</a>\n";
echo "Start: ".$row['Start']."\n";
if($row['Laeuft']) {
echo "<b>Läuft noch bis ".$row['Stop']."</b>\n";
} else {
echo "Ende:".$row['Stop']."\n";
}
echo "</li>\n";
}
echo "</ul>\n";
} else {
echo "<p>\n";
echo " Keine Abstimmungen vorhanden\n";
echo "</p>\n";
}
echo "</div>\n";
break;
?>
Das letzte ist die Detailsübersicht. Diese ist relativ einfach, da man nur zwei Querys an die Datenbank senden muss.
<?php
case 'details':
if(isset($_GET['PollID']) AND $_GET['PollID']) {
$sql = "SELECT
ID,
DATE_FORMAT(Datum,'".DATE_STYLE."') as Start,
Frage,
DATE_FORMAT(DATE_ADD(Datum, INTERVAL 7 Day),'".DATE_STYLE."') as Stop,
NOW() BETWEEN
Datum AND
DATE_ADD(Datum, INTERVAL 7 Day) as Laeuft
FROM
poll
WHERE
ID = '".addslashes($_GET['PollID'])."'";
$pollqry = new Query($sql);
if($pollqry->error()) {
die("<pre>".$pollqry->getError()."</pre>\n");
}
if($polldaten = $pollqry->fetch()) {
echo "<div class=\"polldetails\">\n";
echo " <p>\n";
echo changetext($polldaten['Frage']);
echo " </p>\n";
$sql = "SELECT
Antwort
Klicks
FROM
poll_antworten
WHERE
PollID = '".$polldaten['ID']."';";
$ansqry = new Query($sql);
if($ansqry->error()) {
echo " <pre>\n";
echo $ansqry->getError();
echo " </pre>\n";
die();
}
$sql = "SELECT
SUM(Klicks) as Anzahl
FROM
poll_antworten
WHERE
PollID = '".$polldaten['ID']."';";
$maxqry = new Query($sql);
if($maxqry->error()) {
echo " <pre>\n";
echo $ansqry->getError();
echo " </pre>\n";
die();
}
$maxrow = $maxqry->fetch();
$maxqry->free();
unset($maxqry);
$Anzahl = $maxrow['Anzahl'];
echo " <ul>\n";
while($row = $ansqry->fetch()) {
echo " <li>\n";
if($Anzahl) {
$prozent = $row['Klicks'] / $Anzahl * 100;
$prozent = round($prozent);
echo $prozent."% (".$row['Klicks'].")";
} else {
echo "0% (0)";
}
echo " - ".$row['Antwort']."\n";
echo " </li>\n";
}
echo " </ul>\n";
echo " <p>\n";
echo " Start: ".$polldaten['Start']."<br />\n";
echo " Ende: ".$polldaten['Stop']."<br />\n";
echo " Anzahl Abstimmungen; ".$Anzahl."\n";
echo " </p>\n";
echo "</div>\n";
} else {
echo "<p class=\"error\">\n";
echo " Bitte geben sie eine gültige Poll-ID an.\n";
echo "</p>\n";
}
} else {
echo "<p class=\"error\">\n";
echo " Bitte geben sie die Poll-ID an.\n";
echo "</p>\n";
}
break;
?>
Dies ist unser komplettes Poll-Script. Nun kann man im Adminbereich einen Poll mit beliebig vielen Antworten erstellen.
Fragen zum aktuellen Thema
- Was macht das MySQL-Schlüsselwort BETWEEN?
-
Bei der Angabe BETWEEN muss man noch zwei weitere Werte mit angeben. MySQL guckt dann ob der Wert links vom Wort BETWEEN zwischen den beiden Werten ist, die rechts vom BETWEEN stehen. Die Wörter rechts werden dabei durch das Wort AND getrennt. Dieser Ausdruck liefert dann 0 oder 1, je nach dem ob der Wert zwischen den anderen beiden Werten liegt oder nicht.
- Wie kann ich die Abstimmung schummelsicher machen?
-
Man kann eine Abstimmung nicht schummelsicher machen, aber man kann es den Benutzern erschweren. Dies geht z.B. mit einer Cookie- oder IP-Sperre. Mit diesem Theman befasst sich auch die php-FAQ.