Aufbau eines 5-Sterne-Bewertungssystems mit jQuery, AJAX und PHP
German (Deutsch) translation by Tatsiana Bochkareva (you can also view the original English article)
In diesem Tutorial erfahren Sie, wie Sie ein Bewertungssystem mit AJAX, PHP und jQuery erstellen. Abstimmungen werden in Echtzeit mit der Magie von AJAX aufgezeichnet und aktualisiert, und wir werden auch die Leistungsfähigkeit von PHP nutzen, sodass Sie nicht einmal eine Datenbank benötigen!
Schritt 1. Erstellen Sie den HTML-Code
Wir werden eine einfache Seite erstellen, auf der zwei Filme aufgelistet sind und auf der Sie sie bewerten können. Dies bedeutet, dass wir die Sterne benötigen, um die aktuelle Bewertung anzuzeigen und die Abstimmung zu ermöglichen. Wir möchten auch, dass in einem Bereich die Gesamtzahl der abgegebenen Stimmen und die aktuelle Bewertung bis auf eine Dezimalstelle angezeigt werden.
Werfen wir einen Blick auf HTML/CSS
1 |
<div class='movie_choice'> |
2 |
Rate: Raiders of the Lost Ark |
3 |
<div id="r1" class="rate_widget"> |
4 |
<div class="star_1 ratings_stars"></div> |
5 |
<div class="star_2 ratings_stars"></div> |
6 |
<div class="star_3 ratings_stars"></div> |
7 |
<div class="star_4 ratings_stars"></div> |
8 |
<div class="star_5 ratings_stars"></div> |
9 |
<div class="total_votes">vote data</div> |
10 |
</div>
|
11 |
</div>
|
12 |
|
13 |
<div class='movie_choice'> |
14 |
Rate: The Hunt for Red October |
15 |
<div id="r2" class="rate_widget"> |
16 |
<div class="star_1 ratings_stars"></div> |
17 |
<div class="star_2 ratings_stars"></div> |
18 |
<div class="star_3 ratings_stars"></div> |
19 |
<div class="star_4 ratings_stars"></div> |
20 |
<div class="star_5 ratings_stars"></div> |
21 |
<div class="total_votes">vote data</div> |
22 |
</div>
|
23 |
</div>
|
Beachten Sie, dass dieser HTML-Code keine Grafiken hat. Sie werden mit CSS hinzugefügt. Wir verwenden nur den HTML-Code, um das Framework zu erstellen, mit dem das Widget funktioniert. Jetzt ist es Zeit, CSS hinzuzufügen.
1 |
.rate_widget { |
2 |
border: 1px solid #CCC; |
3 |
overflow: visible; |
4 |
padding: 10px; |
5 |
position: relative; |
6 |
width: 180px; |
7 |
height: 32px; |
8 |
}
|
9 |
.ratings_stars { |
10 |
background: url('star_empty.png') no-repeat; |
11 |
float: left; |
12 |
height: 28px; |
13 |
padding: 2px; |
14 |
width: 32px; |
15 |
}
|
16 |
.ratings_vote { |
17 |
background: url('star_full.png') no-repeat; |
18 |
}
|
19 |
.ratings_over { |
20 |
background: url('star_highlight.png') no-repeat; |
21 |
}
|
Dieser erste Teil des CSS führt einige Dinge aus:
- Gibt den Standardstart "leer" für jede Sternposition an
- Richtet Klassen für ausgefüllte Sterne und hervorgehobene Sterne ein
- Definiert und formatiert den Container der Sterne.
Sie können entweder die im Download bereitgestellten Grafiken verwenden oder Ihre eigenen erstellen. Für jeden der drei Zustände muss eine Grafik vorhanden sein: leer, voll und hervorgehoben.
Weiter fügen wir etwas mehr CSS hinzu, um das Feld für die Gesamtzahl der Stimmen zu positionieren, und zentrieren die Widgets so, dass die Seite mit der Grafik am Anfang dieses Abschnitts übereinstimmt.
1 |
.total_votes {
|
2 |
background: #eaeaea; |
3 |
top: 58px; |
4 |
left: 0; |
5 |
padding: 5px; |
6 |
position: absolute; |
7 |
} |
8 |
.movie_choice {
|
9 |
font: 10px verdana, sans-serif; |
10 |
margin: 0 auto 40px auto; |
11 |
width: 180px; |
12 |
} |
Schritt 2. Hinzufügen der UI-Interaktivität
Zu diesem Zeitpunkt haben wir einen sehr schlicht aussehenden Haufen leerer Sterne, aber sie tun zu diesem Zeitpunkt nicht viel. Hier kommt jQuery zur Rettung.
Unser erster Schritt ist das Hinzufügen von Mouseover- und Mouseout-Handlern für die Sterne. Wir müssen den Stern hervorheben, über dem sich die Maus befindet, und alle vorhergehenden Sterne.
1 |
$('.ratings_stars').hover( |
2 |
// Handles the mouseover
|
3 |
function() { |
4 |
$(this).prevAll().andSelf().addClass('ratings_over'); |
5 |
$(this).nextAll().removeClass('ratings_vote'); |
6 |
},
|
7 |
// Handles the mouseout
|
8 |
function() { |
9 |
$(this).prevAll().andSelf().removeClass('ratings_over'); |
10 |
set_votes($(this).parent()); |
11 |
}
|
12 |
);
|
Wir nutzen die leistungsstarke .prevAll() von jQuery. und .nextAll() Methoden, um die Sterne vor und nach dem aktuell überstrichenen Stern zu erhalten.
Der obige Code fügt dann die Klassen hinzu und entfernt sie, um die Sterne unter der Maus und vor "hervorgehoben" und die Sterne nach "nicht hervorgehoben" zu machen.
Was ist mit set_votes()?
Das ist eine Funktion, die prüft, welche Sterne sich im Status "full" befinden sollen, und eng mit dem nächsten Schritt verknüpft ist, bei dem wir entfernte Daten vom Server abrufen.
Schritt 3. Daten vom Server abrufen
Unsere Sterne werden hervorgehoben, wenn Sie die Maus darüber bewegen, und das ist ein guter Anfang. Aber was ist mit den roten Sternen, die die aktuelle Abstimmung anzeigen? Um diesen Schritt zu erreichen, müssen wir sowohl die Informationen vom Server abrufen als auch JavaScript schreiben, um diese Daten zu verarbeiten.
1 |
$('.rate_widget').each(function(i) { |
2 |
var widget = this; |
3 |
var out_data = { |
4 |
widget_id : $(widget).attr('id'), |
5 |
fetch: 1 |
6 |
};
|
7 |
$.post( |
8 |
'ratings.php', |
9 |
out_data, |
10 |
function(INFO) { |
11 |
$(widget).data( 'fsr', INFO ); |
12 |
set_votes(widget); |
13 |
},
|
14 |
'json' |
15 |
);
|
16 |
});
|
Dieser Codeblock - eigentlich das gesamte JavaScript - befindet sich in einem document.ready-Block. Dieser spezielle Code wird sofort ausgeführt. Es fragt den Server ab und erhält einige Informationen zu jedem Abstimmungs-Widget auf der Seite.
Zuerst richten wir ein Objekt, out_data, ein, das die Informationen enthält, die wir an den Server senden. Unser PHP-Skript erwartet, dass beim Abrufen von Daten "fetch" angezeigt wird. Daher fügen wir es hier ein. Wir geben auch die ID des Widgets an, mit der das serverseitige Skript weiß, nach welchen Daten wir suchen. Wenn die Rückruffunktion ausgelöst wird, enthält sie ein JavaScript-Objekt, das folgendermaßen aussieht:
1 |
{
|
2 |
"widget_id" : "r1", |
3 |
"number_votes" : 129, |
4 |
"total_points" : 344, |
5 |
"dec_avg" : 2.7, |
6 |
"whole_avg" : 3 |
7 |
}
|
Die .data()-Methode ist ein bisschen jQuery-Magie, mit der Sie beliebige Daten mit dem Objekt zuordnen
können.
Wenn Sie sich den Code genau ansehen, werden Sie sehen, dass wir dieses Objekt (gespeichert in der Variablen INFO) und nehmen
etwas damit machen über die .data() Methode.
Die .data() -Methode ist ein bisschen jQuery-Magie, mit der Sie einem DOM Objekt beliebige Daten zuordnen
können. In diesem Fall speichern wir die Daten im Widget div. Es kann später wie folgt zugegriffen werden:
1 |
$('#one_of_your_widgets).data('fsr').widget_id; |
set_votes(), Endlich.
Nachdem die Daten vom Server zurückgegeben wurden, werden sie indirekt an set_votes() übergeben.
1 |
function set_votes(widget) { |
2 |
|
3 |
var avg = $(widget).data('fsr').whole_avg; |
4 |
var votes = $(widget).data('fsr').number_votes; |
5 |
var exact = $(widget).data('fsr').dec_avg; |
6 |
|
7 |
$(widget).find('.star_' + avg).prevAll().andSelf().addClass('ratings_vote'); |
8 |
$(widget).find('.star_' + avg).nextAll().removeClass('ratings_vote'); |
9 |
$(widget).find('.total_votes').text( votes + ' votes recorded (' + exact + ' rating)' ); |
10 |
}
|
Die ersten drei Zeilen dienen der Lesbarkeit, da diese Variablennamen ziemlich lang sind. Schauen wir uns also an, was hier passiert.
Zeile 7: 'avg' ist eine ganze Zahl, die den gerundeten Stimmendurchschnitt dieses Widgets darstellt. Weil es
Mit einer Zahl von 1 bis 5 können wir den richtigen Stern im Widget finden und ihn drehen
vorhergehende zu unserer 'gefüllten' Grafik. Beachten Sie die Verwendung von .andSelf(), um den Stern einzuschließen, der
wir ausgewählt haben.
Zeile 8: Dies ist Zeile sieben ziemlich ähnlich, aber wir entfernen die gefüllte Grafik von späteren Sternen. Dies
ist erforderlich, falls der Durchschnitt für dieses Widget seit der letzten Abstimmung gesunken ist.
Zeile 9: Hier aktualisieren wir das graue Feld unter dem Widget, das eine genauere Bewertung anzeigt.
und lässt einen Besucher wissen, wie viele Stimmen abgegeben wurden.
Schritt 4. Lassen Sie die Abstimmung beginnen
Der letzte Schritt für die Benutzeroberfläche besteht darin, die Abstimmung zu aktivieren. Wir werden jedem Stern einen Klick-Handler hinzufügen. Dieser Klick-Handler ist für das Senden der Abstimmungsdaten an den Server verantwortlich.
Hier ist der Klick-Handler:
1 |
$('.ratings_stars').bind('click', function() { |
2 |
var star = this; |
3 |
var widget = $(this).parent(); |
4 |
|
5 |
var clicked_data = { |
6 |
clicked_on : $(star).attr('class'), |
7 |
widget_id : widget.attr('id') |
8 |
};
|
9 |
$.post( |
10 |
'ratings.php', |
11 |
clicked_data, |
12 |
function(INFO) { |
13 |
widget.data( 'fsr', INFO ); |
14 |
set_votes(widget); |
15 |
},
|
16 |
'json' |
17 |
);
|
18 |
});
|
In diesem Codeblock erstellen wir zunächst einige Variablen, nicht nur aus Gründen der Übersichtlichkeit, sondern in diesem Fall, damit sie innerhalb des .post-Rückrufs verwendet werden können. Denken Sie daran, dass der Klick-Handler den Sternen zugewiesen ist. Daher benötigen wir auch diese zweite Variable, das Widget, damit das Objekt die Daten enthält.
Zuerst richten wir unsere ausgehenden Daten ein, die wir in das Objekt clicked_data einfügen. Wir greifen auf die Klasse zu, die einen Klassennamen im Format star_# enthält, der uns mitteilt, welche Stimme abgegeben wird, und bereiten uns darauf vor, diese zusammen mit der Widget-ID an den Server zu senden.
Die Widget-ID ist der Eckpfeiler, auf den sich dieses Abstimmungssystem stützt. Es ermöglicht uns, unsere gespeicherten Daten nachzuschlagen und diese Daten dem Besucher einfach anzuzeigen.
Schließlich senden wir diese Informationen online an den Server. Der Server fügt die Abstimmung zu den aktuellen Summen hinzu und sendet Informationen mit den aktualisierten Daten an den Browser zurück. Die vom Widget angezeigten Werte werden dann mit set_votes() aktualisiert.
Schritt 5. PHP: Erstellen der Klasse
Nachdem die Benutzeroberfläche fertig ist, müssen wir ein serverseitiges Skript erstellen, um Abstimmungsdaten zu speichern und abzurufen.
Wir werden in PHP eine sehr einfache Klasse namens "Ratings" erstellen und damit Serveranforderungen für unser Bewertungssystem bearbeiten. Es gibt nur zwei Methoden plus den Aufruf. Die Verwendung unserer Klasse wird folgendermaßen aussehen:
1 |
# New Object
|
2 |
$rating = new ratings($_POST['widget_id']); |
3 |
|
4 |
# either return ratings, or process a vote
|
5 |
isset($_POST['fetch']) ? $rating->get_ratings() : $rating->vote(); |
Wenn Sie zu Abschnitt 4 zurückkehren, werden Sie sehen, dass wir die Daten mit der Variablen 'fetch' laden - das ist es, wonach wir hier in Zeile fünf suchen. Wenn es nicht festgelegt ist, verarbeiten wir eine Abstimmung.
Das erste, was wir uns ansehen werden, ist der Beginn der Klasse und insbesondere des Konstruktors.
1 |
class ratings { |
2 |
|
3 |
private $data_file = './ratings.data.txt'; |
4 |
private $widget_id; |
5 |
private $data = array(); |
6 |
|
7 |
function __construct($wid) { |
8 |
|
9 |
$this->widget_id = $wid; |
10 |
|
11 |
$all = file_get_contents($this->data_file); |
12 |
|
13 |
if($all) { |
14 |
$this->data = unserialize($all); |
15 |
}
|
16 |
}
|
serialize() und unserialize sind eine großartige Möglichkeit zum einfachen Speichern
PHP-Datenstrukturen auf der Festplatte.
In sehr wenigen Zeilen ist hier viel los, also werde ich die wichtigen Punkte behandeln.
Zeile 3: Das muss auf eine Textdatei festgelegt werden, in der Sie Ihre Daten speichern möchten. Wir verwenden für dieses Projekt keine Datenbank, obwohl dies leicht möglich ist. Eine einfache Datei wird für unsere Bedürfnisse ausreichen.
Zeile 7: Der Konstruktor. Dies wird aufgerufen, wenn wir unser Objekt erstellen und sofort die ID des Widgets speichern.
Zeile 11: Wir versuchen die Textdatei zu laden. Wenn die Datei nicht existiert, ist das in Ordnung, aber auf einigen Systemen müssen Sie sie im Voraus erstellen und ihr die richtigen Berechtigungen erteilen, damit PHP sie lesen und schreiben kann.
Zeile 14: Diese Zeile ist wichtig. Es nimmt die Daten aus der Textdatei - falls vorhanden - und unserializes() sie. Die Datei enthält ein komplexes PHP-Array, das über serialize() in eine Nur-Text-Darstellung konvertiert wurde, sodass wir es speichern und später als Array wieder einlesen können.
Schritt 6. Die Methode get_ratings().
Diese Methode wird entweder alleine oder von der vote() -Methode aufgerufen. Es findet die Daten für eine bestimmte Widget-ID und gibt sie im JSON-Format an die anfordernde Seite zurück.
1 |
public function get_ratings() { |
2 |
if($this->data[$this->widget_id]) { |
3 |
echo json_encode($this->data[$this->widget_id]); |
4 |
}
|
5 |
else { |
6 |
$data['widget_id'] = $this->widget_id; |
7 |
$data['number_votes'] = 0; |
8 |
$data['total_points'] = 0; |
9 |
$data['dec_avg'] = 0; |
10 |
$data['whole_avg'] = 0; |
11 |
echo json_encode($data); |
12 |
}
|
13 |
}
|
Das sieht nur kompliziert aus - es ist eigentlich ziemlich einfach. Als erstes prüfen wir, ob das in $this->data gespeicherte Array einen Schlüssel hat, der mit unserer Widget-ID übereinstimmt. In diesem Fall geben wir nur diese Informationen zurück, da dies die Widgetdaten sind, die die Seite angefordert hat.
Wir müssen mit diesen Daten nichts anfangen, da sie bereits in Array-Form vorliegen. $this->data ist nur ein Array von Arrays. Wir codieren das gewünschte Array mit json_encode() und senden es an den Browser zurück.
Wenn für die von uns angeforderte Widget-ID keine Daten vorhanden sind, erstellen wir einen Datensatz mit allen Nullwerten und senden ihn an den Browser zurück.
Schritt 7. Die vote()-Methode
Als nächstes müssen wir eine Methode erstellen, um eingehende Stimmen zu verarbeiten. Wenn die Methode beendet ist, muss sie get_ratings() aufrufen, um die aktualisierten Informationen an den Webbrowser zurückzusenden.
Der Methodenstart
1 |
public function vote() { |
2 |
# Get the value of the vote
|
3 |
preg_match('/star_([1-5]{1})/', $_POST['clicked_on'], $match); |
4 |
$vote = $match[1]; |
Das erste, was wir tun, ist den Wert der Abstimmung zu erhalten. Denken Sie daran, dass irgendwo in 'clicked_on' ein Klassenname im Format star_# steht. "star_4" zum Beispiel. Um diesen Wert zu erhalten, verwenden wir einen regulären Ausdruck und erfassen den Wert der Zahl in $match[1].
Die Methode Mitte
1 |
|
2 |
$ID = $this->widget_id; |
3 |
# Update the record if it exists
|
4 |
if($this->data[$ID]) { |
5 |
$this->data[$ID]['number_votes'] += 1; |
6 |
$this->data[$ID]['total_points'] += $vote; |
7 |
}
|
8 |
# Create a new one if it does not
|
9 |
else { |
10 |
$this->data[$ID]['number_votes'] = 1; |
11 |
$this->data[$ID]['total_points'] = $vote; |
12 |
}
|
Hier speichern wir $this->widget_id aus Gründen der Übersichtlichkeit in $ID - der folgende Code wird ohne ihn etwas rau auf den Augen.
Wir prüfen, ob Informationen für diese ID vorhanden sind, und fügen in diesem Fall der Gesamtzahl der Stimmen eine Stimme hinzu und addieren die Punkte aus der erhaltenen Stimme. Dies ist eine laufende Summe aller Stimmen; Wenn also eine Person fünf Sterne und eine andere drei Sterne gibt, sind das insgesamt acht Punkte.
Wenn der Datensatz nicht vorhanden ist, erstellen wir einen mit einer Stimme und nur die Punkte aus der eingehenden Stimme.
Ende
1 |
|
2 |
$this->data[$ID]['dec_avg'] = round( $this->data[$ID]['total_points'] / $this->data[$ID]['number_votes'], 1 ); |
3 |
$this->data[$ID]['whole_avg'] = round( $this->data[$ID]['dec_avg'] ); |
4 |
|
5 |
file_put_contents($this->data_file, serialize($this->data)); |
6 |
$this->get_ratings(); |
7 |
}
|
Sobald wir die Stimmen- und Punktesummen aktualisiert haben, müssen wir sowohl den als ganze Zahl ausgedrückten Durchschnitt als auch einen Dezimalpunkt berechnen. Um zu vermeiden, dass Sie zweimal rechnen müssen, berechnen wir zuerst den Durchschnitt in Zeile eins auf eine Dezimalstelle und runden diesen dann in Zeile zwei auf eine ganze Zahl ab.
In Zeile vier speichern wir die geänderten Informationen wieder auf der Festplatte, nachdem wir sie mit serialize() verarbeitet haben. Sobald die Daten sicher gespeichert sind, rufen wir $this->get_ratings() auf, um die neuen, aktualisierten Informationen an den Browser zu senden.
Abschluss
Der Einfachheit halber ist dies keine 100% ige Komplettlösung. Um dieses Projekt zu erweitern, sollten wir ein Cookie speichern, um sicherzustellen, dass die Leute nur einmal abstimmen oder sogar die IP-Adresse aufzeichnen. Es ist auch möglich, dass zwei Paare mit der ersten Stimme gleichzeitig auftreten und nur eine aufgezeichnet wird. Es ist jedoch ein guter Anfang und mehr als geeignet, um die Stimmen einiger weniger Artikel auf Ihrer Website zu verfolgen. Gedanken? Danke fürs Lesen!



