13
Tags:
php
Skrevet af
Bruger #8331
@ 04.05.2008
Introduktion
I denne artikel vil du lære at lave et rating-system i stil med det,
du kan se i artikler her på Udvikleren.dk.
Artiklen kræver grundlæggende kendskab til PHP og MySQL.
Hvad er et rating-system?
Et rating-system er en funktion, der gør det muligt for brugere at bedømme
("rate") artikler, nyheder etc. Brugeren vil kunne se den gennemsnitlige rating, der
ligner noget i stil med: "Denne artikel har en rating på: 4,7".
Dette har du garanteret også lagt mærke til i artikler her på Udvikleren.dk.
Hvordan fungerer det?
Systemet fungerer ved, at hver gang en bruger bedømmer en artikel, vil hans/hendes
bedømmelse blive lagt oveni den nuværende, der er i databasen.
Eksempel:
Den totale rating i databasen er 100.
En bruger bedømmer en artikel med en 5'er ("Du får en stor femtal af mig!").
Dette tal (5) vil så blive lagt oveni den totale rating i databasen:
100 + 5 = 105
Så nu er den totale rating altså 105.
Samtidig med, at dette sker, bliver et andet felt i databasen inkrementeret med 1.
Dette vil sige, at der bliver lagt 1 til tallet, så hvis feltet, som vi kalder "count",
er 16, vil dette tal efter bedømmelsen være 17. Dette tal bruger systemet, når det
regner den gennemsnitlige rating ud.
Eksempel:
Total rating: 40
Count: 11
Gennemsnit: 40 / 11 = 3,6
Har du styr på det nu? Så lad os komme igang med at kode!
Databasen
Lad os starte med at få styr på vores database.
Opret en database, som du kalder rating.
Derefter udfører du følgende SQL-forespørgsel i den netop oprettede database:
CREATE TABLE `ratings` (
`id` int(11) NOT NULL auto_increment,
`count` INT (4) NOT NULL,
`totalrating` INT (9) NOT NULL,
PRIMARY KEY (`id`)
)
Feltet "id" angiver id'et på artiklen eller nyheden, som rating'en hører til.
Feltet "count" indeholder antal stemmer, som vi skal bruge for at regne gennemsnittet ud.
Feltet "totalrating" indeholder den totale bedømmelse (alle brugernes bedømmelser lagt sammen).
Nu har vi vores database og tabel klar, lad os komme igang med PHP-koden.
Rate.php
Dette er den fil, hvor brugeren kan bedømme en artikel, og det er også den samme
fil, der tilføjer bedømmelsen til databasen. Du kan naturligvis dele koden op, hvis du ikke vil have
det hele i én fil.
Vi springer direkte ud i koden:
<?php
// opret forbindelse til databasen (husk at udfylde brugernavn + password)
$con = mysql_connect("localhost", "", "");
mysql_select_db("rating", $con);
Her opretter vi forbindelse til databasen og vælger databasen "rating", som vi
oprettede lige før.
// tjek om variablen 'rating' er sat
if (isset($_POST['rating'])) {
$rating = $_POST['rating'];
if ($rating > 5) { // tjek om rating er mere end 5
print "Du kan ikke rate mere end 5!";
} else if ($rating < 1) { // tjek om rating er mindre end 1
print "Du kan ikke rate mindre end 1!";
} else {
// læg rating'en oveni den nuværende totale rating, og inkrementér count med 1
// id'et henter vi med GET
$id = addslashes($_GET['id']);
mysql_query("UPDATE `ratings` SET `totalrating` = `totalrating`+$rating, `count` = `count`+1 WHERE `id` = '$id'");
}
}
Denne kode siger forhåbenligt lidt sig selv med kommentarerne. Det vi gør, er - kort fortalt:
Vi tjekker om variablen rating er sat. Denne sendes med POST når brugeren bedømmer en artikel.
Derefter tjekker vi om rating er større end 5 eller mindre end 1. Man kan spørge sig selv:
"Hvorfor dog det? Man kan jo bare undlade at give brugeren mulighed for at stemme sådan".
Det er korrekt, men der findes visse programmer, som kan opfange POST-data når de sendes, og
give brugeren mulighed for at ændre i dem - hvilket gør at de f.eks. kan rate en artikel med 999
eller lignende.
Når vi så har tjekket om bedømmelsen er "lovlig", opdaterer vi databasen med den nye bedømmelse.
Lad os gå videre.
// her henter vi ratingens id via GET
// kan selvfølgelig gøres anderledes
$id = addslashes($_GET['id']);
$q = mysql_query("SELECT * FROM `ratings` WHERE `id` = '$id'");
$res = mysql_fetch_array($q);
$total = $res['totalrating'];
$count = $res['count'];
Her trækker vi værdien af count og totalrating ud af databasen og gemmer dem i variablerne $total og $count. Disse skal vi bruge, når vi skal regne gennemsnittet ud som vi kommer til nu.
// tjek om $total eller $count ikke er lig med 0
if ($total != 0 AND $count != 0) {
Her tjekker vi om $total eller $count IKKE er lig med 0. Dette er for at undgå at vi får en grim
"Division by zero"-fejl fra PHP, når vi regner gennemsnittet ud.
$avg = round($total / $count, 1); // regn gennemsnittet ud ved at dividere $total med $count
Her regner vi gennemsnittet ud ved at dividere $total med $count.
Resultatet bliver afrundet og gemt i variablen $avg.
Og nu kommer vi til en overraskelse! Vi skal da selvfølgelig også have en grafisk rating-viser!
En grafisk rating-viser er en lille søjle, der bliver vist inde i en kasse (typisk en tabel),
og jo højere rating'en er, jo længere vil søjlen være. Hvordan laver vi den? Se her:
$width = round(100 / 5 * $avg); // her beregner vi, hvor langt billedet i den grafiske rating-viser skal være
Vi regner ud hvor mange procent billedet skal fylde af tabellen. Tabellen er 100 pixels bred, og den maksimale
bedømmelse er 5. 100 / 5 = 20. Derefter ganger vi dette tal (20) med gennemsnittet.
Lad os sige, at gennemsnittet er 4,5. Regnestykket bliver så: 20 * 4,5 = 90.
Dette vil sige, at søjlen skal være 90% bred i forhold til tabellens bredde. Bredden sætter vi således:
<img src="bar.gif" width="$width%">
Vi indsætter simpelthen billedet "bar.gif", og sætter bredden til $width %.
Så hvis $width er lig med 50, vil koden komme til at se sådan ud, når siden vises:
<img src="bar.gif" width="50%">
Dette kommer jeg lidt mere ind på lige om lidt.
Lad os komme videre med noget mere kode.
} else {
$avg = 0; // sæt $avg til 0 hvis både $total og $n er lig med 0
$width = 0; // det samme med $width
}
Her sætter vi $avg og $width til 0 hvis $total og $n er lig med 0.
Nu skal vi skrive den gennemsnitlige bedømmelse og vise den grafiske rating-viser til brugeren.
// skriv den gennemsnitlige rating til brugeren
print "Denne artikel har en gennemsnitlig rating på $avg";
// opret tabellen, som søjlen skal vises i
echo "<table width=\\"100\\" style=\\"border:solid 1px;\\" cellpadding=\\"0\\">
<tr>
<td><img src=\\"bar.gif\\" width=\\"$width%\\" height=\\"5\\"></td>
</tr>
</table>";
?>
Nu mangler vi blot at oprette den form, hvor brugeren kan bedømme en artikel.
Skriv nedenstående kode nedenunder PHP-koden.
<html>
<head>
<title>Rating-system</title>
</head>
<body>
<form action="" method="POST">
<select name="rating">
<option>Vælg en bedømmelse</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<input type="submit" value="Rate!">
</form>
</body>
</html>
Resultatet bliver en lille dropdown-box, hvor brugeren har mulighed for at vælge imellem 1-5.
Nu er systemet faktisk færdigt! Håber det kan bruges til noget.
Bemærk:Husk at ændre dine filer til at tilføje nyheder og artikler, så følgende SQL-forespørgsel udføres når en nyhed eller artikel tilføjes:
INSERT INTO `ratings` (count, totalrating) VALUES ('0', '0')
Dette er for at oprette en række til bedømmelsen for den nye artikel eller nyhed.
Her er hele koden til rate.php:
rate.php<?php
// opret forbindelse til databasen
$con = mysql_connect("host", "username", "password");
mysql_select_db("rating", $con);
// tjek om variablen 'rating' er sat
if (isset($_POST['rating'])) {
$rating = $_POST['rating'];
if ($rating > 5) { // tjek om rating er mere end 5
print "Du kan ikke rate mere end 5!<br>";
} else if ($rating < 1) { // tjek om rating er mindre end 1
print "Du kan ikke rate mindre end 1!<br>";
} else {
// læg rating'en oveni den nuværende totale rating, og inkrementér count med 1
mysql_query("UPDATE `ratings` SET `totalrating` = `totalrating`+$rating, `count` = `count`+1");
}
}
$q = mysql_query("SELECT * FROM `ratings`");
$r = mysql_fetch_array($q);
$total = $r['totalrating'];
$count = $r['count'];
// tjek om $total eller $count er lig med 0
if ($total != 0 AND $count != 0) {
$avg = round($total / $count, 1); // regn gennemsnittet ud ved at dividere $total med $count
$width = round(100 / 5 * $avg); // her beregner vi, hvor lang billedet i den grafiske rating-viser skal være
} else {
$avg = 0; // sæt $avg til 0 hvis både $total og $n er lig med 0
$width = 0; // det samme med $width
}
// skriv den gennemsnitlige rating til brugeren
print "Denne artikel har en gennemsnitlig rating på $avg";
echo "<table width=\\"100\\" style=\\"border:solid 1px;\\" cellpadding=\\"0\\">
<tr>
<td><img src=\\"bar.gif\\" width=\\"$width%\\" height=\\"5\\"></td>
</tr>
</table>";
?>
<html>
<head>
<title>Rating-system</title>
</head>
<body>
<form action="" method="POST">
<select name="rating">
<option>Vælg en bedømmelse</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<input type="submit" value="Rate!">
</form>
</body>
</html>
OBS: Dette system tjekker ikke, om brugeren har stemt før eller er logget ind. Denne artikel
viser blot princippet i sådan et system.
Det burde dog være meget nemt at bygge systemet sammen med et community, hvor scriptet så tester, om brugernavnet allerede har stemt.
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (13)
God artikel, men måden er nok ikke den mest optimale. F.eks kunne man forestille sig man gerne ville have mere end 1 rating kørende f.eks ved flere artikler og som du selv skriver om brugeren har stemt før. Det kunne laves ved at indsætte en række hvergang en bruger voter også bruge AVERAGE funktionen fra mySQL til at regne gennemsnittet.
Finder det også ret underligt at du har lavet et system der kunne tillader en rating, måske skulle du på føre et id felt til din tabel der autoincrementer, og så en where klausul på din queries der henter ratingen for at bestemt id.
Ja, det har I da fuldstændig ret i, at det er tosset at systemet kun tillader én rating af gangen. Jeg får lige skrevet noget her en dag hvor jeg har tid.
Jeg synes sådan set, at det er en ganske udemærket artikel. Der er naturligvis den lille detalje, at man kun kan have en rating kørende, men en løsning som tillader n ratings kan hurtigt implementeres i koden herover.
Jeg synes at der er mange ting som gør at artiklen er god:
- Dine variabler hedder noget som giver mening, og ikke bare $flaf1 og $flaf2
- Du laver validering af input
- Du flyver ikke rundt mellem php og html som ellers er på mode
Der er også nogle lidt sjove ting (synes jeg)
- Du laver en tabel med totalrating og count som heltal, men du tester om de er forskellig fra strengen "0" - hvorfor ikke bare 0?
- Du har (så vidt jeg kan se) en fejl i din validering:
$total = $r['totalrating'];
$count = $r['count'];
// tjek om $total eller $count er lig med 0
if ($totalrating != "0" AND $count != "0") {
$avg = round($total / $count, 1); // regn gennemsnittet ud ved at dividere $total med $count
$width = round(100 / 5 * $avg); // her beregner vi, hvor lang billedet i den grafiske rating-viser skal være
} else {
$avg = 0; // sæt $avg til 0 hvis både $total og $n er lig med 0
$width = 0; // det samme med $width
}
...Du hiver totalrating ud i $total, men undersøger $totalrating!="0" i if-sætningen
Tak for ros og lidt kritik, JT
Jeg snakker lige med Kasper (TSW) her en dag, for at få rettet de fejl du omtaler + skrevet lidt ekstra, så der er mulighed for at have mere end én rating kørende af gangen.
Så er fejlene rettet, og der er nu mulighed for at have flere ratings kørende på én gang
God artikel, kan lide den måde du gennemgår hver enkelt "del" af koden. Tit bliver det bare her er koden og her er hvad den gør.
Har selv lavet et lignende system den eneste forskel er bare at min version nok er en smule upræcis, men tilgengæld sparer man masser af plads i databasen, ved at regne gennemsnitet ud, så i stedet for at gemme total, så gemmer den det nye facit. Via fx sådan en kode (hvis man har stemt 3:
$new_number = $db_number + 1;
$new_rating = ($db_rating * $db_number + 3) / $new_number;
Det ville være dejligt hvis du skrev en måde hvorpå du kan undgå at man bare trykker "opdater" masser af gange for at øgeratingen, har jeg nemlig selv problemmer med, da mit session går i ged.
@ Michael:
Jeg skal nok se en dag, om jeg kan få lavet noget, så man kun kan stemme én gang pr. rating.
Eventuelt gemme IP-addressen i databasen, når der stemmes.
Problemmet er jo at man gemmer alt for meget data hvis man gemmer IP-adresser for dem der stemmer, alt for besværligt, det burde kunne gøres med cookies elelr sessions. (Mere midlertidigt end permanent)
Cookies.. Ja, det kunne da godt lade sig gøre, men så er det bare at rydde sine cookies, så kan man stemme igen.
Og ja, man kunne da også lade sine sessions leve noget længere, men heller ikke det er en holdbar løsning, hvis det kun skal være muligt at stemme én gang.
Jeg lægger hovedet i blød.
Jeg synes det er en Fint artikke, jeg fårstår i hvert fald PHP bedre med hensyn til mysql
Jeg synes også det er en rigtig fin artikel, men jeg forstår ikke hvordan bar.gif skal se ud?
@ Emilie
Undskyld for det meget sene svar (har ikke været herinde i lang tid).
bar.gif er bare et billede, som er 1 pixel bred, og x antal pixels høj (x kan du selv bestemme, alt efter dit behov).
I denne artikel er den dog 5 pixels høj, hvilket sådan set er for lidt, men det er nemt at ændre.
Det er meget nemt og hurtigt at lave billedet i f.eks. Paint:
1. Åbn Paint og tryk Ctrl+E.
2. I vinduet der popper op, skriver du "1" i boksen ud for bredde, og "5" i boksen ud for højde.
3. Tryk OK.
4. Zoom ind, så det er nemmere at "ramme" det hvide område, og udfyld derefter området med en farve efter eget valg.
5. Gem billedet som bar.gif.
Men som sagt anbefaler jeg at lave billedet højere end 5 pixels, da det ikke er heeelt vildt stort. 10 eller derover er bedst.
Husk at ændre højden i følgende kode, hvis du ændrer højden på billedet:
<td><img src=\\"bar.gif\\" width=\\"$width%\\" height=\\"[b]5[/b]\\"></td>
Du skal være
logget ind for at skrive en kommentar.