Hier nun ein Tutorial für ein
Umfragescript mit MySQL.
Ich habe alle Funktionen, die sich mit MySQL verbinden, weggelassen.
Nun zunächst die Projektbeschreibung:
Das Umfragescript soll folgende Punkte leisten:
- Anlegen von beliebig vielen Umfragen (zeitgesteuert)
- Automatische Darstellung der Umfragen
- Automatische Auswertung der Umfragen und deren Darstellung
Zunächst werden wir nur Umfragen erstellen, die "entweder oder“-Antworten (Beispielsweise: Bewertung nach Schulnoten 1-6) haben. Sprich: Formulare mit Radiobuttons.
Die Tabellenstruktur sieht also folgendermaßen aus:
1. Umfragen
id BIGINT (11) AUTO_INCREMENT
Die ID ist natürlich obligatorisch. Damit haben wir die Möglichkeit Datensätze eineindeutig zuzuweisen.
Frage TEXT
Jetzt auch noch die Beschreibung/Frage einer Umfrage. Beispiel: "Wie bewertet ihr dieses Tutorial?“
Begin_t BIGINT(11)
Nun speichern wir den Beginn der Umfrage als UNIX-Timestamp. 11 Ziffern sollten für die nächsten Jahre ausreichen.
End_t BIGINT(11)
Und das Ende der Umfrage als UNIX-Timestamp.
2. Antworten
id BIGINT(11) AUTO_INCREMENT
umfrage_id BIGINT(11)
Damit wir auch wissen zu welcher Umfrage die Antwortmöglichkeiten gehören.
Antwort VARCHAR(255)
Die Antwort als Text.
Farbe VARCHAR(6)
Weil wir lustig sind Farben für die einzelnen Antworten im HEX RGB-Wert für HTML. Die Farben sollen später für die Ergebnisanzeige verwendet werden.
Übrigens könnt ihr das Ganze natürlich auch mit Background-Images machen. Sieht dann schöner aus.
3. Werte
id BIGINT(11) AUTO_INCREMENT
umfrage_id BIGINT(11)
antwort_id BIGINT(11)
Anzahl BIGINT(11)
Und die Anzahl der Stimmen für die Antwort.
4. IP-Check
Wir brauchen noch ein IP-Check, damit jeder Benutzer einer IP, auch nur einmal abstimmen kann. Diese Vorgehensweise hat natürlich auch ihre Schwächen. Alle User, die über einen Proxy-Server kommen, können z.B. nicht mehr abstimmen, wenn auch nur einer von ihnen eine Stimme abgegeben hat. Natürlich ist es auch möglich die IP zu verschleiern etc. Aber für dieses Tutorial soll es mal ausreichen.
Id BIGINT(11) AUTO_INCREMENT
Ip_addr VARCHAR(255)
Timestamp BIGINT(11)
Nach 24 Stunden (?) sollte die IP wieder von der Sperrliste verschwinden. Bei dynamisch vergebenen IPs auch selbstverständlich.
So, nun beginnen wir mit dem IP-Check. Weil es so einfach ist, und wir warm werden wollen.
Die erste Funktion soll uns eine IP in die Sperrliste eintragen und (24 h) alte Datensätze löschen.
Anmerkung: Alle Tabellen- und Spaltennamen werden mit blöden Namen bezeichnet. Also nicht unbedingt mit copy & paste arbeiten.
[PHP-Doku]
MySQL-Funktionen
Funktion time ()
PHP-Code:
<?
function insert_ip_lock ()
{
$timeout = 86400; // Sekunden, bis ein Datensatz gelöscht wird.
//Der aktuelle Timestamp (time () ) minus dem Timestamp der Einträge ergibt die Differenz bis dato. Soll 24 Stunden nicht übersteigen.
$query = "DELETE FROM IP-Check WHERE " . time () . " - Timestamp > $timeout";
// Die "die"-Anweisung soll uns auch mal den mySQL-Fehler anzeigen (mysql_error () ).
$q = @mysql_query ($query) or die ("MySQL-Fehler: " . mysql_error () );
// So, jetzt der neue Datensatz mit IP-Adresse und aktueller Zeit.
// $_SERVER[REMOTE_ADDR] enthält die IP-Adresse des Clients. Leider enthält die PHP-Doku keineList der verfügbaren $_SERVER Variablen. Also mal phpinfo () aufrufen, um alle globalen Variablen zu sehen.
$query = "INSERT INTO IP-Check (Ip_addr, timestamp) VALUES ('" . $_SERVER[REMOTE_ADDR] . "', " . time () . ")";
$q = @mysql_query ($query) or die ("MySQL-Fehler: " . mysql_error () );
if ($q)
{
return TRUE;
} else {
return FALSE;
}
}
?>
Und jetzt die Funktion, die checkt ob eine IP bereits vorhanden ist.
PHP-Code:
<?
function check_ip_lock ()
{
$query = "SELECT id FROM IP-Check WHERE Ip_addr = '" . $_SERVER[REMOTE_ADDR] . "'";
$q = @mysql_query ($query) or die ("MySQL-Fehler: " . mysql_error () );
// Hier ist der Ausdruck der Funktion absichtlich vertauscht. Also TRUE, wenn kein Datensatz vorhanden ist.
if (mysql_num_rows ($q) > 0)
{
return FALSE;
} else {
return TRUE;
}
}
?>
Soweit alles klar?
Dann können wir ja zum Anlegen von neuen Umfragen übergehen.
Anmerkung: Ich werde die Funktionen einfach mal hinklatschen. Wie ihr diese Funktionen in eure Seite einbindet, bleibt euch überlassen.
Eine ganz angenehme Funktion, die uns Optionen für ein <SELECT>-Tag mit den Monatsnamen erstellt.
PHP-Code:
<?
Function insert_monate_options ()
{
$monate = array (
1 => "Januar",
2 => "Februar",
3 => "März",
4 => "April",
5 => "Mai",
6 => "Juni",
7 => "Juli",
8 => "August",
9 => "September",
10=> "Oktober",
11=> "November",
12=> "Dezember"
);
foreach ($monate as $id=>$monat)
{
echo "
<option value='$id'>$monat
";
}
}
?>
Hier zunächst das Admin-Formular:
HTML-Code:
<form method='POST'>
<t e x t a r e a name='f' cols='50' rows='20'></t e x t a r e a> Frage/Beschreibung<br>
Beginn der Umfrage<br>
<input type='text' size='2' maxlength='2' name='b_d'> . <select name='b_m' size='1'>
<?
insert_monate_options ();
?>
</select> . <input type='text' size='4' maxlength='4' name='b_y'><br>
Ende der Umfrage<br>
<input type='text' size='2 maxlength='2' name='e_d'> . <select name='e_m' size='1'>
<?
insert_monate_options ();
?>
</select> . <input type='text' size='4' maxlength='4' name='e_y'><br>
<br>
<input type='submit' value='Anlegen'>
</form>
Natürlich braucht ihr auch noch einige “Hidden”-Input Felder, damit die Daten auch richtig weiterverarbeitet werden.
Übrigens: Zum Nachbearbeiten bereits angelegter Datensätze, würde ich dasselbe Formular verwenden. Mit der Übergabe einer ID (z.B. über $_GET["id“]), wird erkannt, dass hier eine Änderung stattfinden soll.
Also:
PHP-Code:
<?
If (isset ($_GET["id"]) )
{
// Alle Daten aus MySQL holen
$daten = "SELECT … ";
$chng = TRUE;
}
?>
und dann im Formular:
PHP-Code:
<input … <? If ($chng) { echo "value='" . $datenblabla . "'"; } ?> ... >
und am Ende:
PHP-Code:
<? If ($chng) { echo "<input type='hidden' name='id' value='" . $datenidblabla . "'>"; } ?>
Soweit hierzu. Kann natürlich auch in anderen Formularen so angewandt werden. In der Funktion, die die Daten in die Tabelle einträgt, muss natürlich auch eine Weiche eingebaut werden, die erkennt, ob $_POST["id“] gesetzt ist. Falls ja, wird ein "UPDATE“-Query erstellt, ansonsten ein "INSERT“-Query.
Hier die Funktion, die die Daten einträgt. Nur mit INSERT. Den Rest überlasse ich euch.
[PHP-Doku]
Funktion mktime ()
PHP-Code:
<?
function insert_new_poll ()
{
// jetzt erstellen wir erst einmal Timestamps für die Daten. Intval (), damit wir wenigstens ein wenig fehlertolerant sind (Falls jemand Buchstaben oder sonstigen Müll einträgt). Siehe auch Doku mktime (). Wir gehen immer von 0:00:00 Uhr aus.
$begin = mktime (0, 0, 0, intval ($_POST["b_m"]), intval ($_POST["b_d"]), intval ($_POST["b_y"]);
// Wir addieren nochmals 24 Stunden, denn die Umfrage soll ja bis einschließlich des letzten Tages laufen.
$end = mktime (0, 0, 0, intval ($_POST["e_m"]), intval ($_POST["e_d"]), intval ($_POST["e_y"]) + 68400;
$query = "INSERT INTO Umfragen (Frage, Begin_t, End_t) VALUES ('" . $_POST["f"] . "', $begin, $end)";
$q = @mysql_query ($query) or die ("MySQL-Fehler: " . mysql_error () );
// Wenn alles geklappt hat, wollen wir die neue ID der Umfrage haben
if ($q)
{
return mysql_insert_id ();
} else {
return FALSE;
}
}
?>
Jetzt wollen wir die verschiedenen Antworten eintragen können. Ich gehe mal davon aus, dass man schon vorher weiß wie viele Antworten es gibt.
Ach, schreiben wir uns doch noch eine Funktion, die alle Datensätze, die wir herauslesen schon indiziert und assoziiert ausgibt. Also: $Daten[DATENSATZ_NUMMER]["Feld-Name"]
PHP-Code:
<?
function give_ret ($table, $clause)
{
$query = "SELECT * FROM $table $clause";
$q = mysql_query ($query) or die ("Error while retrieving data!<br>query: $query<br>" . mysql_error ());
$anz = mysql_num_rows ($q);
if ($anz > 0)
{
for ($i = 0; $i < $anz; $i++)
{
$ret[$i] = mysql_fetch_assoc ($q);
}
} else {
$ret = FALSE;
}
return $ret;
}
?>
Zunächst (aus Usability-Gründen) eine Funktion, die alle Optionen eines <SELECT>-Tags erstellt für alle Umfragen, die wir haben.
PHP-Code:
<?
function insert_poll_options ()
{
$polls = give_ret ("Umfragen", "");
foreach ($polls as $poll)
{
echo "
<option value='" . $poll["id"] . "'>" . $poll["Frage"] . "
";
}
}
?>
Und damit das Formular für die Antworten:
PHP-Code:
<form method='POST'>
Umfrage: <select name='u' size='1'>
<? insert_poll_options (); ?>
</select>
Antworten: <input type='text' size='2' maxlength='2' name='a'>
<input type='submit'>
</form>
Dann erstellen wir uns ein Formular mit den Antworten.
PHP-Code:
<form method='POST'>
<?
for ($i = 0; $i < $_POST["a"]; $i++)
{
echo "
Antwort " . ($i + 1) . ":<br>
<input type='text' size='50' maxlength='255' name='antwort[$i]'><br>
Farbe: #<input type='text' size='6' maxlength='6' name='farbe[$i]'>
";
}
?>
<input type='submit'>
<input type='hidden' name='umfrage_id' value='<? echo $_POST["u"]; ?>'>
</form>
Wie ihr seht, brauchen wir auch die ID der Umfrage.
Wir speichern uns alle Daten gleich in Arrays (name=’antwort[$i]’). Das geht mit PHP.
Übrigens: Wenn ihr anders vorgehen möchtet, fühlt euch frei. Dies ist nur eine Idee. Ich habe auch gar nichts getestet, also: keine Garantie.
Jetzt die Funktion, die uns die Daten einträgt.
PHP-Code:
<?
Function insert_umfrage_antworten ()
{
// Einzelne Querys für jeden Datensatz. Die Datensätze werden auch in der Reihenfolge eingetragen, in der diese in das Formular eingetragen wurden.
foreach ($_POST["antwort"] as $id=>$a)
{
$query = "INSERT INTO Antworten (umfrage_id, Antwort, Farbe) VALUES (" . $_POST["umfrage_id"] . ", '$a', '" . $_POST["farbe"][$id] . "')";
$q = @mysql_query ($query) or die ("MySQL-Fehler: " . mysql_error () );
$antwort_id = mysql_insert_id ();
// Und auch gleich die Werte für die Antworten. Natürlich mit 0 Stimmen für neu angelegte Antworten
$query = "INSERT INTO Werte (umfrage_id, antwort_id, Anzahl) VALUES (" . $_POST["umfrage_id"] . ", $antwort_id, 0)";
$q = @mysql_query ($query) or die ("MySQL-Fehler: " . mysql_error () );
}
}
?>
So, jetzt haben wir das Anlegen von Umfragen fertig. Also weiter mit der Darstellung einer Umfrage. Zuerst die Umfrage-Box, Umfrage-Popup, Umfrage BLAH.
PHP-Code:
<?
function show_umfragen ()
{
// unsere give_ret Funktion von weiter oben.
$umfragen = give_ret ("Umfragen", "WHERE Begin_t < " . time () . " AND End_t > " . time ());
if (is_array ($umfragen) )
{
foreach ($umfragen as $umfrage)
{
// Für jede Umfrag ein Formular
echo "
<form method='POST'>
<b>" . $umfrage["Frage"] . "</b><br>
";
$antworten = give_ret ("Antworten", "WHERE umfrage_id = " . $umfrage["id"]);
foreach ($antworten as $a)
{
// Jetzt erstellen wir uns die Radio-Buttons. Falls wir mehrere Umfragen gleichzeitig haben (wollen wir das überhaupt?), benennen wir diese mit "a“ + Umfrage_id. Dann sind die Namen eineindeutig.
echo "
<input type='radio' name='a" . $umfrage["id"] . "' value='" . $a["id"] . "'>" . $a["Antwort"] . "<br>
";
}
echo "
<input type='submit'>
<input type='hidden' name='umfrage_id' value='" . $umfrage["id"] . "'>
";
}
}
}
?>
Alles klar?
Dann machen wir uns an das Eintragen der Stimme.
PHP-Code:
<?
function insert_umfrage_stimme ()
{
// Hat der User bereits abgestimmt?
if (check_ip_lock () )
{
// Jetzt darf er nimmer
insert_ip_lock ();
$query = "UPDATE Werte SET Anzahl = Anzahl + 1 WHERE umfrage_id = " . $_POST["umfrage_id"] . " AND antwort_id = " . $_POST["a" . $_POST["umfrage_id"]];
$q = @mysql_query ($query) or die ("MySQL-Fehler: " . mysql_error () );
return $q;
} else {
echo "Sie haben bereits abgestimmt.";
return FALSE;
}
}
?>
So, jetzt können wir uns an die Auswertung machen.
PHP-Code:
<?
// Jetzt geben wir der Funktion einfach mal die Umfrage-ID mit. Wie gesagt: alles einfach nur beispielhaft
function html_show_auswertung ($umfrage_id)
{
// Jetzt ein kleines Query, aus dem wir die Antwort-ID, den Antwort-Text, die Farbe und die dazugehörigen Stimmen erhalten.
$query = "SELECT Antworten.Antwort as antwort, Antworten.Farbe as farbe, Werte.Antwort_id AS antwort_id, Werte.Anzahl AS anzahl FROM Werte, Antworten
WHERE Werte.Antwort_id = Antworten.id AND Antworten.Umfrage_id = $umfrage_id";
$q = @mysql_query ($query) or die ("MySQL-Fehler: " . mysql_error () );
// Die Summe aller Antworten ist erstmal Null.
$summe = 0;
for ($i = 0; $i < mysql_num_rows ($q); $i++)
{
$antworten[$i] = mysql_fetch_assoc ($q);
// Hier addieren wir die Anzahl der Stimmen. Naja, hätte man auch über das MySQL-Query lösen können
$summe += $antworten[$i]["anzahl"];
}
if ($summe == 0)
{
// Sonst müssten wir gleich durch Null teilen. Also lieber nicht.
echo "Es wurden bisher keine Stimmen abgegeben.";
} else {
// Diese Variable setzt uns die Breite eines Balkens bei 100%
$max_width = 200;
echo "
<table border='0' cellpadding='4' cellspacing='0'>
";
foreach ($antworten as $a)
{
// Für jede Antwort, eine Zeile
echo "
<tr>
<td>
" . $a["antwort"] . "
</td>
<td>
<table border='0' cellpadding='0' cellspacing='0' style='background-color: #" . $a["farbe"] . "'>
<tr>
";
// Jetzt die prozentuale Berechnung. [0-1] * Maximale Breite. Ok?
echo "
<td width='" . (($a["anzahl"] / $summe) * $max_width) . "'>
</td>
</tr>
</table>
</td>
</tr>
";
}
echo "
</table>
";
}
}
?>
So, und damit wären wir auch schon fertig. Ich hoffe, dass das Tutorial hilfreich war. Und hoffentlich funktioniert auch alles. Wie gesagt: Dieses Tutorial soll das Thema nur kurz anreißen, und zu weiteren Verbesserungen anreizen.
Viel Spaß.
Lesezeichen