copyright (c)  2003   useGroup
PHP

Jochen Stärk
PHP-Tutorial
Ein Counter

nach untenEinführung
nach untenErste Schritte
nach untenZugriff in die Datenbank schreiben
nach untenTodo's

Einführung

nach obenEinführung 

Counter arbeiten normalerweise mit aus Ziffern erzeugten Bildern oder als Bilder zurückgegebenen Strings. Das geht unter PHP zwar auch aber nur mit der gd-Bibliothek (die Bilder erzeugen kann). Diese Bibliothek ist allerdings nicht in unserem Testsystem vorgesehen und überhaupt (sie ist TIERISCH schwer zu installieren, zumindest unter Linux) eher selten installiert. Ausserdem ist diese Lösung irgendwie witzlos und so möchte ich einen anderen Lösungsweg vorschlagen: Wir binden als externe JavaScript-Datei eine PHP-Datei ein. Diese liefert einen Javascript-Quelltext -- und zwar die funktion getVisitors die als Integer die Anzahl der Besucher zurückliefert. Mit

<script language="JavaScript">
document.writeln(getVisitors());
</script>
kann man diese dann in der HTML-Datei ausgeben - oder auch nicht, falls nicht gewünscht. Vorteil: Extrem wenig Daten (Text statt Grafik) werden übermittelt, die Daten bleiben dynamisch (JavaScript-Funtkionen könnten die Ziffern auch mit Bildern anzeigen oder bei dem 1000sten Besucher Alarm schlagen), es funktioniert unter allen Browsern, man muss die Visitors nicht darstellen falls ein stiller Counter gewünscht ist und die Sache braucht erheblich weniger Rechenaufwand als eine Grafiklösung (für Serverbetreiber interessant).

Nachteil

bei ausgeschaltetem JavaScript funktioniert gar nichts und Netscape ist pingelig: sollte der Counter ausfallen sieht man unter netscape auch die dahinterliegende Seite nicht.

Features

Unser Counter soll neben den Anzahlen der Besuchen für den Administrator auch festhalten, zu welchem Zeitpunkt von welcher IP ein Zugriff erfolgte (um später Statistiken erzeugen zu können, teilweise müsste man dazu eben doch die GD-Bibliothek benutzen) und von welcher URL der Benutzer kam (wichtig um z.b. den Erfolg von eintragungen in Suchmaschinen zu sehen). Hierzu bieten sich (Filter, Gruppierfunktionen, Skalierbarkeit) wieder einmal Datenbanken an.


Erste Schritte

nach obenErste Schritte 

Als HTML-Datei brauchen wir wie gesagt eine Datei, die eine externe Datei mit <script src=""> einbindet.


<html>
<script language="JavaScript" src="counter.php">

</script>

<body>
Sie sind der <b><script>document.write(getVisitors());</script></b>te Besucher
</body>

</html>
und als PHP-Datei (im Besipiel angesprochen: counter.php) schreiben wir zuesrt einmal eine PHP-Datei die nur eine mit-eins-belegter Variable ausgibt.
function getVisitors()
{
  <?php  $i=1; ?>
  return <?php echo "$i"; ?>;
}
Beachten Sie dabei, dass die Variable im ersten Block <?php... ?> im zweiten unverändert vorhanden sind. So gesehen sind die Blöcke also global. Ausserdem ist es hier verlockend function getVisitors() { $i=1; <?php echo $i; ?> } zu schreiben, was aber nicht funktioniert, weil dann $i bestenfalls eine Javascript-Variable ist und PHP sie nicht einsehen, geschweige denn mit echo ausgeben kann.


Zugriff in die Datenbank schreiben

nach obenZugriff in die Datenbank schreiben 

Um den Zugriff in eine Datenbank zu schreiben, muss dort zuerst die entsprechende Tabelle vorliegen. Diese erzeugen wir mit einer Datei namens Setup.php. Die Datenbank soll enthalten:

Ein Feld für die IP (text)

Ein Feld für die Zugriffszeit (integer)

und ein Feld für die vorherige Seite (text).

Das Datumsfeld machen wir Integer um ein Unix-Timestamp einfügen zu können - mit den Dingern lässt sich i.d.R. viel leichter Rechnen als mit Formatierten Datumsangaben.

Das machen wir mit einer Datei setup.php die ähnlich des ersten Teiles der Beispieldatei im Einrichten eines eigenen Testsystems aufgebaut ist - und die gleiche Funktion hat.

<html>
Starte Setup für Counter....
<?php
$dbh = odbc_connect('testdb', 'aname', 'apwd', SQL_CUR_USE_ODBC);
echo "Connected to db $dbh<br>";

$query = "drop table counter";
$res = odbc_exec($dbh, $query);
$query = "create table counter (zeitpunkt int, ip char(15), refferer char(255))";
$res = odbc_exec($dbh, $query);
odbc_close_all();
?>
... beendet
</html>
Die Tabelle wird gedroppt bevor sie angelegt wird um Änderungen (z.b. Einfügen eines neuen Feldes) später wirklich wirksam zu machen und nicht an einer Fehlermeldung a lá die Tabelle existiert schon scheitern zu lassen.

Diese Datei sollte man allerdings nach Gebrauch in ein anderes Verzeichnis das nicht von außen angegriffen werden kann verschieben, weil ansonsten jemand auf die Idee kommen könnte pfadname/setup.php aufzurufen und die gesamten counterdaten (drop table) löscht. Ein Umbenennen in ein Format das nicht automatisch ausgeführt wird (z.b. in setup.html) wäre noch um einiges schlimmer, da im odbc-connect, das dann im Quelltext im Klartext stünde, alle Daten (Benutzername und Passwort) der Datenbank enthält und Datenbanken i.d.R. auch von außen über eine Internetverbindung abgefragt werden können - Vollzugriff mit lesen, schreiben, ändern und löschen für den Angreifer wären die Folge.

Zurück zum eigentlichen: Die Datei counter.php müsste jetzt noch folgendermaßen geändert werden:
function getVisitors()
{
<?php
  $dbh = odbc_connect('testdb', 'aname', 'apwd', SQL_CUR_USE_ODBC);
  $now = time();
  $ip = getenv("REMOTE_ADDR");
  $ref = getenv("HTTP_REFERER");
  $query = "insert into counter values ($now, '$ip', '$ref')";
  $res = odbc_exec($dbh, $query);
  $query = "select * from counter";
  $res = odbc_exec($dbh, $query);
  $numrows = odbc_num_rows($res);

  odbc_close_all();
?>
  return <?php echo "$numrows"; ?>;
}
time() gibt den schon angesprochenen Unix-Timestamp zurück (auch unter Windows ;)), REMOTE_ADDR und HTTP_REFERER sind Umgebungsvariablen die IP des Users anzeigen bzw. wo er herkommt und odbc_num_rows gibt die Anzahl der Datensätze zurück.

Zu schade, dass HTTP_REFERER immer den Namen der HTML-Datei zurückgibt, da diese die scheinbar letzte ist, die vor der PHP-Datei "angezeigt" wird. Ein weiterer Schwachpunkt meiner Counter-Einbindung, aber ich denke, die Vorteile überwiegen dennoch.


Todo's

nach obenTodo's 

Als to-do braucht der Programmierer noch unbedingt


copyright (c)  2003   useGroup