Intelligentes Bewertungssnippet
von Hannes am 08.06.2011 in My Modx mit 1 Kommentar
Tweet
Neben Star-Ratings möchte man auch Wertungen feingranularer erfassen können. Mit diesem kleinen Snippet ist es möglich für eine Seite, für ein Video usw. Wertungspunkte zwischen 0 und 100 pro Seite zuvergeben. Die Auswertung läuft automatisch im Hintergrund.
MySQL als Grundelement
Für dieses Snippet, wie auch schon zuvor für den Page Hit Counter, verwende ich MySQL Tabellen um alles aufzuzeichen. Manche würden auch auf Text Dateien zugreifen wollen. MySQL ist aber viel handlicher, übersichtlicher und besitzt mehr Möglichkeiten mit den Daten umzugehen. Alles Weitere ist sehr simple Mathematik. Wir summieren alle Punkte, die auf einer Seite (identifiziert durch die eindeutige ID) abgegeben wurden, auf und teilen sie durch die Anzahl der abgegeben Stimmen. Das ergibt uns eine Zahl, die wir noch auf ganze Punkte auf- bzw. abrunden und spucken diese wieder an gewünschten Stellen aus. Zusätzliche geben wir dem ganzen noch eine kleine IP Sperre mit, sodass nicht ein und die gleiche Person mehrmals abstimmen kann.
Die Installation
Zunächst erstellen wir uns eine Konfigurationsdatei namens rateit.config.php:
<?php
// Verbindung zum Datenbankserver
mysql_connect(
"Dein Host", // Host
"Dein Benutzername", // User
"Dein Passwort" // Passwort
) or die("Keine Verbindung zum Datenbankserver!");
// Der Name der Datenbank muss angegeben werden!
mysql_select_db("Datenbankname")
or die("Die Datenbank ist momentan nicht erreichbar!");
?>
Danach folgt das Erstellen (rateit.installation.php) der Tabellen in unserer MySQL Datenbank:
<?php
include("rateit.config.php");
$sql = "CREATE TABLE `modx_rateit_ip` (
`ip` VARCHAR( 24 ) NOT NULL PRIMARY KEY ,
`zeit` INT NOT NULL ,
`page` VARCHAR( 10 ) NOT NULL
) ENGINE = MYISAM ;
";
if (mysql_query($sql)) {
echo "<p>Tabelle `modx_rateit_ip` wurde erstellt.</p>";
}
$sql = "CREATE TABLE `modx_rateit_stats` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`page` VARCHAR( 10 ) NOT NULL ,
`rate` INT NOT NULL ,
`ratings` INT NOT NULL ,
UNIQUE (
`page`
)
) ENGINE = MYISAM ;
";
if (mysql_query($sql)) {
echo "<p>Tabelle `modx_rateit_stats` wurde erstellt.</p>";
}
?>
Wichtig dabei ist, dass beide Dateien im gleichen Verzeichnis abgelegt sind, sonst müsste man in den Includebefehl modifizieren.
Das Rate It Snippet
Der Code zum Rate It Snippet:
<?php
// Rating Snippet "Rate It"
// @author Hannes Letsch, Tohanwabones.de
// @copyright Copyright 2010-2011, Hannes Letsch
// @version 1.0.1 - June 21, 2011
include("rateit.config.php");
$ip = $_SERVER["REMOTE_ADDR"];
$page = $modx->resource->get('id');
// Ist die Seite schon angelegt?
if (!mysql_fetch_row(mysql_query("SELECT `page` FROM `modx_rateit_stats` WHERE `page` = '" . $page . "'"))) {
// Nein, dann bitte Zeile anlegen
mysql_query("INSERT INTO `modx_rateit_stats` (`page`,`rate`,`ratings`) VALUES ('" . $page . "','0','0')");
}
// Alte IP-Adresse löschen
$ablaufzeit = time() - 300; // 300 Sekunden (= 5 Min.) IP Sperre!
mysql_query("DELETE FROM `modx_rateit_ip` WHERE `zeit` <= " . $ablaufzeit . "");
if ($_POST['buttonRate']) {
$yourRate = $_REQUEST["inputRate"];
if ($yourRate <= 100) {
// Ist die IP-ADresse schon eingetragen?
if (!mysql_fetch_row(mysql_query("SELECT `ip` FROM `modx_rateit_ip` WHERE `ip` = '" . $ip . "ID". $page . "' "))) {
// Nein, IP-Adresse, Timestamp und gehörige Seiten ID eintragen
mysql_query("INSERT INTO `modx_rateit_ip` (`ip`,`zeit`,`page`) VALUES ('" . $ip . "ID". $page . "','" . time() . "','" . $page . "')");
// Counter aktualisieren
mysql_unbuffered_query("UPDATE `modx_rateit_stats` SET `rate` = `rate` + $yourRate , `ratings`= `ratings`+ 1 WHERE `page` = '" . $page . "'");
} else { $errorIP = "Bitte nur einmal bewerten."; }
} else { $errorVote = "Erlaubte Werte: 0 bis 100"; }
}
//Auswertung
$selectRate = mysql_fetch_assoc(mysql_query("SELECT `rate` FROM `modx_rateit_stats` WHERE `page` = '" . $page . "'"));
$selectRatings = mysql_fetch_assoc(mysql_query("SELECT `ratings` FROM `modx_rateit_stats` WHERE `page` = '" . $page . "'"));
$articleRate = $selectRate['rate'];
$articleRatings = $selectRatings['ratings'];
if ($articleRatings > 0) {
$allRate = floor($articleRate/$articleRatings);
} else { $allRate = 0; }
mysql_close();
//Templating
$tpl = $modx->getOption('tpl',$scriptProperties,'outputRateIt');
// Aufstellung der placeholders:
$modx->setPlaceholder('valuation', $allRate);
$modx->setPlaceholder('votes', $articleRatings);
$modx->setPlaceholder('accumulation', $articleRate);
$modx->setPlaceholder('error.ip', $errorIP);
$modx->setPlaceholder('error.vote', $errorVote);
//Gib mir aus, was ich will.
$output = $modx->getChunk($tpl);
return $output;
Das Einstellen des Chunks
Zunächst einmal rufen wir auf der gewünschten Seite unser Snippet auf:
[[!rateIt? &tpl=`myTemplate`]]
Zu beachten ist dabei, dass wir mit Hilfe von &tpl unseren Chunk ansteuern, in dem der eigentliche html Output enthalten ist. Verweisen wir nicht, so wird standardmäßig auf den Chunk outputRateIt verwiesen. Exsitiert dieser auch nicht, sehen wir einfach nichts. Deshalb muss der Chunk "outputRateIt" noch erstellt werden.
Die Placeholder für Rate it sind:
- [[+votes]]: Wie viele Stimmen wurden abgegeben?
- [[+valuation]]: Die eigentliche Wertung.
- [[+accumulation]]: Alle abgegebenen Punktzahlen aufsummiert.
- [[+error.vote]]: Fehlermeldung: Wenn ein Wert außerhalb des Intervalls 0-100 eingegben wurde.
- [[+error.ip]]: Fehlermeldung: Wenn man schon abgestimmt hat.
Der Chunk braucht nun noch ein Input Field und einen Submit Button, sodass das Ganze ins Rollen kommt. Wichtig dabei ist die Bezeichunung "buttonRate" für den Submit Button und für das Eingabefeld dementsprechend "inputRate". Ein Beispiel wäre:
<input type="text" name="inputRate" value="Deine Bewertung" onfocus="this.value=''; this.onfocus=null;" /> <input type="submit" name="buttonRate" value="✔" />













Tohuwabohu 21.06.2011 um 22:04
Ein kleines Update: Selbstverständlich sollte man nicht durch 0 teilen. Deshalb habe ich gerade eben den Snippet Code modifiziert. Anstatt einfach wild durch floor($articleRate/$articleRatings) zurechnen, habe ich das Ganze noch in eine kleine if Abfrage eingebettet. Damit wäre auch das Problem gelöst :).
Antworten