Bewertungssystem für Bilder in der Galerie verstehen

 

Fünf kleine Sterne unter einem Foto, daneben „4,4 bei 27 Stimmen“: So sieht ein Bewertungssystem für Bilder meistens aus. Hinter dem Klick steckt eine Rechnung mit Tücken: Ein Bild mit zwei begeisterten Stimmen landet schnell vor einem, das fünfzig Menschen gut fanden. Hier lesen Sie, wie Sie fair rechnen, Mehrfachstimmen bremsen und was das Nachrüsten im Bildergalerie-Script verlangt.

Bewertungssystem für Bilder gewichtet: Foto A fällt mit 2 Stimmen von 5,0 auf 4,0, Foto B mit 48 Stimmen nur von 4,6 auf 4,5

So rechnet ein Bewertungssystem für Bilder

Jeder Klick auf einen Stern wird auf dem Server zu einer Zeile in einer Datenbanktabelle: Bildnummer, vergebener Wert, Zeitpunkt und eine Kennung des Besuchers. Die Zahl neben dem Foto ist der Durchschnitt dieser Zeilen. Hat ein Bild 15 Stimmen mit fünf Sternen, 8 mit vier und 4 mit drei, sind das 75 + 32 + 12 = 119 Sterne. Geteilt durch 27 Stimmen ergibt das 4,41, angezeigt als 4,4.

Zeigen Sie neben dem Wert immer die Zahl der Stimmen, denn „4,4“ allein verrät nicht, ob drei Freunde oder dreihundert Fremde abgestimmt haben. Weil jede Stimme eine eigene Zeile ist, rechnet sich der Wert nach dem Löschen von Testklicks einfach neu.

Warum wenige Stimmen täuschen

Nehmen wir eine Galerie, in der ein typisches Bild rund zehn Stimmen hat und eine Stimme im Schnitt 3,8 Sterne vergibt. Foto A hat zwei Stimmen mit je fünf Sternen, also 5,0. Foto B steht mit 48 Stimmen und 221 Sternen bei 4,6, Foto C mit 20 Stimmen und 86 Sternen bei 4,3. Vorn liegt Foto A, obwohl dort vielleicht nur der Fotograf und seine Schwester geklickt haben.

Fairer ist der gewichtete Durchschnitt, oft Bayes-Durchschnitt genannt. Dabei rechnen Sie jedem Bild so viele gedachte Stimmen hinzu, wie ein typisches Bild hat, hier also zehn, jede mit dem Galerieschnitt von 3,8. Foto A kommt so auf (10 × 3,8 + 10) ÷ 12 = 4,0, Foto B auf (38 + 221) ÷ 58 = 4,5 und Foto C auf (38 + 86) ÷ 30 = 4,1. Bei Foto A stellen die gedachten Stimmen 10 von 12, bei Foto B nur 10 von 58.

Im Diagramm sehen Sie oben, wie sich die Reihenfolge umdreht, und unten, wie viel Gewicht die gedachten Stimmen bei jedem Foto haben.

Animiertes Rechendiagramm: drei Fotos nach einfachem und nach gewichtetem Durchschnitt mit zehn gedachten Stimmen sortiert; Foto A mit nur zwei Stimmen rutscht von Platz eins auf Platz drei, Balken zeigen den Anteil der gedachten Stimmen von 10 von 12, 10 von 30 und 10 von 58
Zwei Stimmen mit fünf Sternen reichen nicht für Platz eins: Je weniger echte Stimmen ein Foto hat, desto näher rückt es an den Durchschnitt der Galerie.

Die Zahl der gedachten Stimmen ist Ihre Stellschraube. Entspricht sie der Stimmenzahl eines typischen Bildes, überwiegt der eigene Wert eines Fotos erst, wenn es mindestens so viel Zuspruch hat wie die meisten anderen. Sammeln die Bilder mit der Zeit mehr Stimmen, erhöhen Sie die Zahl.

Sterne, Daumen oder Herz?

Welche Form der Abstimmung passt, hängt davon ab, was Sie aus den Ergebnissen lernen wollen:

FormStärkeSchwächePasst zu
Ein bis fünf Sternebekannt aus Shops, fein genug für eine Ranglisteviele vergeben nur einen oder fünf SterneFotowettbewerb, offene Reisegalerie
Daumen hoch und runterzeigt auch, was nicht gefälltMinusstimmen kränken, ohne zu sagen, warumFotokurs, Auswahl für einen Kalender
Daumen hoch oder Herzein Klick, keine schlechten Notenmisst nur Zustimmung, kein MissfallenVereins- und Familienfotos

In einer Galerie, die vor allem Freunde und Familie besuchen, ist das Herz meist die ehrlichere Wahl: Niemand möchte dem Hochzeitsfoto der Cousine zwei Sterne geben. Einen Durchschnitt gibt es dann nicht, die Rangliste zählt einfach die Herzen.

Mehrfachstimmen und Datenschutz

Sollen Besucher ohne Anmeldung abstimmen, muss der Server selbst erkennen, wer schon abgestimmt hat. Dafür gibt es zwei gängige Sperren, und jede hat für sich eine Lücke:

  • Cookie als Sperre: Der Browser merkt sich, dass er abgestimmt hat. Wer das Cookie löscht oder ein privates Fenster öffnet, stimmt erneut ab.
  • IP-Adresse als Sperre: Eine Familie hinter einem Router teilt sich eine Adresse und wäre nach der ersten Stimme gesperrt. Handys im Mobilfunknetz wechseln ihre Adresse dagegen oft.

Deshalb arbeiten beide zusammen: Das Cookie fängt den versehentlichen zweiten Klick ab. Ein Skript dagegen verwirft jedes Cookie und holt sich vor jeder Stimme ein neues, sodass nur noch die Obergrenze je IP-Adresse greift. Fünf Stimmen je Bild und Tag reichen für eine vierköpfige Familie samt Gast am selben Router und stoppen ein Skript nach der fünften Stimme. Eine Anmeldepflicht lohnt sich erst bei einem Wettbewerb mit Preis.

Beide Sperren gehören mit Zweck und Speicherdauer in die Datenschutzerklärung. Ein Cookie, das nur vermerkt, dass dieser Browser abgestimmt hat, dient einer Funktion, die der Besucher selbst auslöst. Nach verbreiteter Auslegung von § 25 TDDDG braucht es dafür keine Einwilligung im Cookie-Banner. Im Beispielcode weiter unten gilt das Cookie 365 Tage, die IP-Adresse wird nach sieben Tagen gelöscht.

Gefragte Fotos ohne Sterne erkennen

Das Bildergalerie-Script bringt kein Bewertungssystem für Bilder mit. Um zu sehen, welche Fotos ankommen, und die besten nach vorn zu holen, reicht oft, was es hat:

ZielWeg ohne Sterne
Beliebte Kategorien erkennenAufrufe der Kategorie-Adresse, etwa bildergalerie.php?kid=5, im Zugriffsprotokoll des Webhosters zählen.
Beliebte Einzelbilder erkennenAbrufe der Datei für die große Ansicht zählen: bei großen Fotos die Kopie bilder/tn/ob_5_dateiname.jpg, sonst das Original im Kategorieordner.
Bestenliste zeigenEine Kategorie wie „Unsere schönsten Bilder“ anlegen und die Spitzenreiter dort erneut hochladen, denn verschieben kann die Galerie Bilder nicht.
Lieblingsbild nach vorn holenBilder erscheinen in der Reihenfolge des Hochladens, das erste ist zugleich Titelbild der Kategorie. Das stärkste Foto also zuerst hochladen.

Abrufzahlen einzelner Bilder sind nur ein Anhaltspunkt, weil die Lightbox das vorige und das nächste Foto gleich mitlädt. Mehr dazu in Statistik der Galerie auswerten und Zähler für Bildaufrufe.

Sterne im Bildergalerie-Script nachrüsten

Wer trotzdem Sterne möchte, muss sie selbst programmieren. Ein Plugin-System gibt es nicht, und die Vorlage tpl/bildergalerie.html enthält nur die Platzhalter {AUSGABE_BILDERGALERIE} und {AUSGABE_KATEGORIE}. Der Umbau besteht aus vier Schritten:

  1. Tabelle anlegen. Neben der Tabelle bilder speichert bilder_bewertung jede Stimme als eigene Zeile.
  2. Bildnummer in die Seite schreiben. Die Links der Vorschaubilder in inc/functions.php bekommen ein Attribut wie data-bild="17".
  3. Stimme annehmen. Eine neue Datei bewertung.php im Hauptordner prüft und speichert sie.
  4. Sterne in der großen Ansicht zeigen. In js/lightbox.js nimmt die Lightbox die Bildnummer mit in ihre Liste imageArray auf, zeichnet unter der Beschreibung fünf Sterne und schickt einen Klick an bewertung.php.

Die Datei bewertung.php prüft jede Stimme in vier Stufen. Bringt der Browser noch kein Cookie bg_stimme mit, bekommt er eine neue Zufallskennung, und die Stimme zählt. Ein zweiter Klick auf dasselbe Bild scheitert an Stufe 4, weil die Datenbank jede Kennung nur einmal je Bild annimmt. Ein Skript, das Cookies verwirft, stoppt erst die IP-Grenze in Stufe 3.

Animiertes Ablaufdiagramm: bewertung.php prüft eine Stimme für Bild 17 in vier Stufen, gültiger Wert, Cookie bg_stimme oder neue Kennung, IP-Grenze von 5 Stimmen je Bild in 24 Stunden und 60 je Stunde, Bild vorhanden und Kennung neu; ein zweiter Klick wird nicht gezählt, ein Skript endet mit 429
Ein neuer Besucher bekommt das Cookie und seine Stimme zählt, ein zweiter Klick auf dasselbe Bild scheitert an Stufe 4, ein Skript mit immer neuen Cookies an Stufe 3.

Wer PHP und JavaScript sicher beherrscht, braucht dafür etwa einen Arbeitstag. Der Haken liegt bei Updates: Laut Anleitung überschreiben Sie dabei alle Dateien, also müssen Sie Ihre Änderungen an inc/functions.php und js/lightbox.js danach neu einpflegen. bewertung.php und die Tabelle bleiben erhalten. Die zwei Kästen zeigen den Code, Nicht-Programmierer können sie überspringen.

Für Entwickler: Tabelle und gewichtete Bestenliste (SQL)

IP-Spalte (45 Zeichen, genug für IPv6) und Index ip_zeit sind dem Anmeldeprotokoll admin_log der Galerie nachgebaut.

CREATE TABLE `bilder_bewertung` ( `id` int(11) NOT NULL AUTO_INCREMENT, `bild_id` int(11) NOT NULL, `wert` tinyint(4) NOT NULL, `zeit` int(11) NOT NULL, `kennung` char(64) NOT NULL, `ip` varchar(45) NOT NULL DEFAULT '', PRIMARY KEY (`id`), UNIQUE KEY `einmal` (`bild_id`, `kennung`), KEY `ip_zeit` (`ip`, `zeit`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Ein täglicher Cronjob leert die Adressen nach sieben Tagen: UPDATE bilder_bewertung SET ip = '' WHERE zeit < UNIX_TIMESTAMP() - 7 * 86400

Die Bestenliste rechnet mit zehn gedachten Stimmen und lässt über die Verknüpfung mit bilder Stimmen gelöschter Bilder außen vor.

SELECT b.bild_id, COUNT(*) AS stimmen, ROUND((10 * g.schnitt + SUM(b.wert)) / (10 + COUNT(*)), 1) AS gewichtet
FROM bilder_bewertung b
JOIN bilder ON bilder.id = b.bild_id
CROSS JOIN (SELECT AVG(v.wert) AS schnitt FROM bilder_bewertung v JOIN bilder ON bilder.id = v.bild_id) g
GROUP BY b.bild_id, g.schnitt
ORDER BY gewichtet DESC, stimmen DESC
LIMIT 10;

Bei Herz oder Daumen hoch speichert jede Stimme den Wert 1, und die Rangliste sortiert nach COUNT(*), am besten je Kategorie (WHERE bilder.kategorie_id = 5).

Für Entwickler: Schritt 3, bewertung.php (PHP)

Die Zugangsdaten $db_host, $db_user, $db_passwort und $db_datenbank legt der Installer in inc/config.php an.

<?php
include 'inc/config.php';
header('Content-Type: text/plain; charset=utf-8'); $bild = (int) ($_POST['bild'] ?? 0);
$wert = (int) ($_POST['wert'] ?? 0);
if ($bild < 1 || $wert < 1 || $wert > 5) { http_response_code(400); exit('ungültig');
} // Kennung aus dem Cookie, beim ersten Mal neu erzeugen
$kennung = (string) ($_COOKIE['bg_stimme'] ?? '');
if (!preg_match('/^[0-9a-f]{32}$/', $kennung)) { $kennung = bin2hex(random_bytes(16)); setcookie('bg_stimme', $kennung, [ 'expires' => time() + 365 * 86400, 'path' => '/', 'httponly' => true, 'samesite' => 'Strict']);
} $db = new mysqli($db_host, $db_user, $db_passwort, $db_datenbank);
$db->set_charset('utf8mb4'); // Grenze je IP: 5 Stimmen je Bild in 24 Stunden, 60 je Stunde
$ip = (string) ($_SERVER['REMOTE_ADDR'] ?? '');
$jetzt = time();
$q = $db->prepare('SELECT SUM(bild_id = ?), SUM(zeit > ?) FROM bilder_bewertung WHERE ip = ? AND zeit > ?');
$stunde = $jetzt - 3600;
$tag = $jetzt - 86400;
$q->bind_param('iisi', $bild, $stunde, $ip, $tag);
$q->execute();
$q->bind_result($jeBild, $jeStunde);
$q->fetch();
$q->close();
if ($jeBild >= 5 || $jeStunde >= 60) { http_response_code(429); exit('zu viele Stimmen');
} // nur vorhandene Bilder, je Kennung und Bild einmal
$hash = hash('sha256', $kennung);
$q = $db->prepare('INSERT IGNORE INTO bilder_bewertung (bild_id, wert, zeit, kennung, ip) SELECT id, ?, ?, ?, ? FROM bilder WHERE id = ?');
$q->bind_param('iissi', $wert, $jetzt, $hash, $ip, $bild);
$q->execute();
echo $q->affected_rows === 1 ? 'gezählt' : 'nicht gezählt';

Die 60 je Stunde verhindern, dass ein Skript alle Bilder der Reihe nach bewertet. Bei einem Wettbewerb im Firmen- oder Schulnetz setzen Sie die Grenze je Bild höher.

Wer Schwerpunkte vorerst über Reihenfolge und eigene Kategorien setzt, kann das Bildergalerie-Script kostenlos herunterladen und Sterne später ergänzen.

Häufige Fragen

Diese Fragen kommen zu Sternen in der eigenen Galerie fast immer auf.

Ab wie vielen Stimmen ist der Durchschnitt aussagekräftig?

Eine feste Grenze gibt es nicht. Mit Gewichtung dürfen Sie den Wert früh zeigen, weil sie Ausreißer bremst. Ohne Gewichtung ist es fairer, unter fünf Stimmen „noch zu wenige Stimmen“ statt einer Zahl anzuzeigen und Bilder erst ab etwa einem Dutzend Stimmen in eine Bestenliste aufzunehmen.

Wie entferne ich Stimmen, die nicht zählen sollen?

Über die Spalten zeit und ip: Testklicks löschen Sie mit allen Zeilen vor dem Starttag, Stimmen eines Skripts sieben Tage lang über dessen IP-Adresse. Die Kennung aus dem Cookie hilft dabei nicht, sie liegt in der Tabelle nur als Hashwert vor.

Bringt das Bildergalerie-Script Sterne mit?

Nein, weder Sterne noch Kommentare noch Besucherkonten. Eine Abstimmung lässt sich wie oben beschrieben nachrüsten, die geänderten Dateien müssen aber nach jedem Update neu eingespielt werden.

Verwandte Themen

Kommentare und ihr Schutz vor Spam fehlen dem Script ebenso wie Sterne. Diese Seiten behandeln sie und das Zählen von Aufrufen: