Was soll das Script können?
Das Ganze habe ich in zwei Teile geteilt; das Script aus dem ersten Teil erfüllt die Anforderungen der ersten beiden Punkte, das zweite kann alles geforderte. Zu Demonstrationszwecken wurde das erste Script sowohl ohne als auch mit Datenbank realisiert, das zweite hingegen der Einfachheit halber nur mit Datenbank.
Als erstes stellt sich die Frage, welche Daten gespeichert werden müssen. Im Moment sind das noch nicht viele:
Den ersten Punkt können wir dadurch abhaken, daß wir mit Hilfe der ,directory functions` auslesen lassen, welche Dateien in einem Verzeichnis existieren. Für die Lösung ohne Datenbank habe ich dies auch gemacht, bei der zweiten Variante dagegen alle Dateinamen in eine Tabelle geschrieben und dann aus dieser einen zufälligen Eintrag auswählen lassen. Man könnte dies natürlich kombinieren, indem man ein Script schreibt, was alle möglichen Dateinamen aus dem Verzeichnis ausliest und dann in die Tabelle schreibt, um dann nachher nur mit der Tabelle zu arbeiten.
Die ganze Administrationsoberfläche habe ich bei diesem Beispiel ganz dezent ignoriert; d.h. die Dateinamen müssen von Hand in die SQL-Tabelle eingetragen werden, und wie häufig welches Banner angezeigt wurde, muß ebenfalls von Hand aus den Dateien ausgelesen bzw. aus der Tabelle abgefragt werden.
Bei dem folgenden Script erledigen die beiden Funktionen genau dasselbe - mit dem Unterschied, daß die erste Funktion ohne Datenbank arbeitet.
Noch ein kurzes Wort zu Installation: Beide Funktionen gehen davon aus, daß die Banner im Unterverzeichnis ,banner` liegen. Die Dateisystemvariante benötigt zusätzlich noch ein Verzeichnis, in dem die Dateien zum Zählen liegen, das wird hier ,rw` genannt.
Für die Datenbankversion wird auch eine entsprechende Tabelle benötigt, für die hier die entsprechende create table-Anweisung steht.
CREATE TABLE banner( BID int not null primary key auto_increment, Name varchar(50) not null, shown int, unique(Name) );
Das Script sollte durch die Kommentare eigentlich soweit selbsterklärend sein.
<?php function file_get_name(){ function get_file_array(){ // gibt ein Array mit allen Dateinamen zurück $handle=opendir('banner'); while ($file = readdir($handle)){ if ($file != "." && $file != ".."){ $ret[]=$file; } } return $ret; } // alle Dateinamen in Array schreiben $files = get_file_array(); // Zufall initialisieren srand((double)microtime()*1000000); $nr = rand(0,count($files)-1); // zufällige Datei auswählen $banner = $files[$nr]; //Zähler für Datei erhöhen // Dateiname für Zähler in $filename schreiben $filename = "rw/".$banner; if (file_exists($filename)){ $fp = fopen($filename,"r+"); flock($fp,2); $count = fgets($fp,1024); if (empty($count)){ $count = 0; } $count++; fseek($fp,0); } else { $fp = fopen($filename,"w"); $count = 1; } fwrite($fp,$count); fclose($fp); return $banner; } function db_get_name(){ $DB_HOST = "localhost"; $DB_USER = "cr"; $DB_PASSWD = "123"; $DB_NAME = "cr"; mysql_connect($DB_HOST, $DB_USER, $DB_PASSWD); mysql_select_db($DB_NAME); $res = mysql_query('select BID, Name, BID*0+rand() AS sort from banner order by sort LIMIT 1;'); if (!$res){ // Fehler echo "Fehler in der Datenbank"; return false; } // Ergebnis holen $row = mysql_fetch_array($res); // shown-Zähler um eins erhöhen mysql_query(sprintf('update banner set shown = shown+1 where BID=%d', $row["BID"])); // Bildname zurück geben return $row["Name"]; } ?> <html> <head> <title>Banner</title> </head> <body> <img src="banner/<?php echo file_get_name(); ?>"> <img src="banner/<?php echo db_get_name(); ?>"> </body> </html>
Die Lösung ist relativ einfach. Wir geben nicht die eigentliche URL an, sondern ein Script auf unserem Server, was in Ruhe zählen kann und dann auf die richtige URL weiterleitet. Ich habe das hier in einem Script erledigt.
Aber erstmal zu unserer Tabelle in der Datenbank. Diese muß jetzt natürlich auch nochmal
geringfügig erweitert werden. Es fehlen nämlich die Felder für die Klicks und für die URL. Im
Endeffekt ergibt sich daraus folgendes create table:
CREATE TABLE banner( BID int not null primary key auto_increment, Name varchar(50) not null, URL varchar(100) not null, shown int, clicked int, unique(Name) );
Nun aber zum Script. Der erste Teil (die Funktion ,show_banner`) ist fast identisch mit der Funktion aus der ersten Realisierung. Sie gibt nun allerdings nicht mehr den Bildnamen, sondern das Ganze als Link zurück.
Die größte Änderung befindet sich im Hauptprogramm. Hier wird nun nicht mehr nur die Funktion aufgerufen, sondern es gibt eine Fallunterscheidung. Wird das Ganze ohne ,bid` aufgerufen, so wird das Banner zurückgegeben, ansonsten wird der Klick gezählt und zur URL weitergeleitet.
Die Kombination in einem Script mag für diesen Fall einfacher sein, weil man alles zusammen hat; häufig ist es aber wahrscheinlich besser, diese beiden Funktionen in zwei verschiedene Scripte zu packen.
<?php $DB_HOST = "localhost"; $DB_USER = "cr"; $DB_PASSWD = "123"; $DB_NAME = "cr"; mysql_connect($DB_HOST, $DB_USER, $DB_PASSWD); mysql_select_db($DB_NAME); function show_banner(){ // zufälliges Banner aus DB holen $res = mysql_query('select BID, Name, BID*0+rand() AS sort from banner order by sort LIMIT 1;'); if (!$res){ // Fehler echo "Fehler in der Datenbank"; return false; } // Ergebnis holen $row = mysql_fetch_array($res); // shown-Zähler um eins erhöhen mysql_query(sprintf('update banner set shown = shown+1 where BID=%d', $row["BID"])); // Banner mit Link ausgeben printf('<a href="%s?bid=%d">'. '<img src="banner/%s" border="0"></a>', $_SERVER["PHP_SELF"], $row["BID"], $row["Name"]); } /************* Hauptprogramm *************/ if (isset($_GET["bid"])){ // bid gesetzt -> es wurde auf eine Banner geklick // -> User weiterleiten if (!is_numeric($_GET["bid"])){ // bid muß immer numerisch sein die('Keine gültige ID übergeben'); } // URL aus DB holen $res = mysql_query(sprintf('select URL from banner where bid=%d', $_GET["bid"])); if (!$row = mysql_fetch_array($res)){ // Fehler die("Fehler in der Datenbank"); } // click-Zaehler um eins erhöhen mysql_query(sprintf('update banner set clicked = clicked+1 where BID=%d', $_GET["bid"])); // User auf die richtige Seite weiterleiten header('Location: '.$row["URL"]); exit; } else { // Banner anzeigen ?> <html> <head> <title>Banner</title> </head> <body> <?php show_banner(); ?> </body> </html> <?php } ?>