Ratingsystem i PHP/MySQL

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:

Fold kodeboks ind/udKode 


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:

Fold kodeboks ind/udKode 

Her opretter vi forbindelse til databasen og vælger databasen "rating", som vi
oprettede lige før.

Fold kodeboks ind/udKode 

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.

Fold kodeboks ind/udKode 

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.

Fold kodeboks ind/udKode 

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.

Fold kodeboks ind/udKode 

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:

Fold kodeboks ind/udKode 

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:

Fold kodeboks ind/udKode 

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:

Fold kodeboks ind/udKode 

Dette kommer jeg lidt mere ind på lige om lidt.

Lad os komme videre med noget mere kode.

Fold kodeboks ind/udKode 

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.

Fold kodeboks ind/udKode 

Nu mangler vi blot at oprette den form, hvor brugeren kan bedømme en artikel.
Skriv nedenstående kode nedenunder PHP-koden.

Fold kodeboks ind/udKode 

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:

Fold kodeboks ind/udKode 

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
Fold kodeboks ind/udKode 

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)

User
Bruger #10856 @ 05.05.08 07:39
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.
User
Bruger #5620 @ 05.05.08 18:40
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.
User
Bruger #8331 @ 05.05.08 21:36
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.
User
Bruger #4683 @ 07.05.08 09:56
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:
Fold kodeboks ind/udKode 

...Du hiver totalrating ud i $total, men undersøger $totalrating!="0" i if-sætningen


User
Bruger #8331 @ 07.05.08 21:18
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.
User
Bruger #8331 @ 09.05.08 22:17
Så er fejlene rettet, og der er nu mulighed for at have flere ratings kørende på én gang :)
User
Bruger #14139 @ 01.09.08 19:07
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:

Fold kodeboks ind/udKode 


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.
User
Bruger #8331 @ 15.09.08 08:58
@ 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.
User
Bruger #14139 @ 15.09.08 21:37
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)
User
Bruger #8331 @ 17.09.08 12:08
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.
User
Bruger #13291 @ 11.07.09 16:11
Jeg synes det er en Fint artikke, jeg fårstår i hvert fald PHP bedre med hensyn til mysql
User
Bruger #15190 @ 28.07.09 16:20
Jeg synes også det er en rigtig fin artikel, men jeg forstår ikke hvordan bar.gif skal se ud? :S
User
Bruger #8331 @ 21.10.09 17:04
@ 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:

Fold kodeboks ind/udKode 
Du skal være logget ind for at skrive en kommentar.
t