Author: Progman, zuletzt bearbeitet von progman @ 2005/03/29 11:48:26
Bitte beachten Sie, dass die Tutorialkapitel zusammenhängen. Wenn sie direkt auf ein Kapitel verlinkt wurden müssen Sie gegebenenfalls die vorherigen Kapitel auch lesen. Achten Sie beim lesen darauf, dass Sie kein Kapitel überspringen.
Eigenes User-Online-Script
1. Wie Funktioniert ein User-Online Script
Auf manchen Seiten findet man eine Angabe User Online: 5. Doch so eine Angabe ist nie richtig. Dafür ist das HTTP-Protokol einfach nicht ausgelegt. Der Webserver weiß nicht ob der User noch die Seite offen hat oder den Browser schon längst geschlossen hat. Wir als Programmiere müssen schätzen wie lange so ein User sich auf einer Seite aufhält. Was wir eher sagen können ist Anzahl User der letzen x Minuten. Wir zählen die Klicks der User und geben dann entsprechend aus wieviele User in den letzen x Minuten (oder auch x Sekunden) auf der HP waren.
2. Layout der MySQL-Tabelle
Um einen Benutzer zu erkennen benutzen wir seine IP-Adresse. Und was wir auch noch speichern müssen ist die genaue Zeitangabe, wann der User mit dieser IP-Adresse eine Seite geöffnet hat. Das sind also 2 Spalten die wir brauchen. Ich nenn die mal IP und Datum. Diese Spalten speichern wir in eine Tabelle Online.
CREATE TABLE Online ( IP VARCHAR(15), Datum DATETIME );
Die Spalte IP ist vom Typ VARCHAR(15). Eine IP-Adresse ist ja wie folgt aufgebaut: XXX.XXX.XXX.XXX. Insgesammt sind das 15 Zeichen. 4 Mal 3 Zeichen für die Zahlen (12) und 3 mal den Punkt, sind 15 Zeichen. Also kann eine IP-Adresse (IPv4 versteht sich) maximal aus 15 Zeichen bestehen (dot-Schreibweise).
In der Spalte Datum wird dann das Datum gespeichert, wann der User mit der IP-Adresse die Seite als letzes Besucht hat. Dieses Datum müssen wir beim jeden Klick des Users aktuallisieren.
3. Aufbau des Scripts
Was muss das Script machen? Einmal muss es einen neuen Eintrag in der Tabelle hinzufügen, fallst ein Surfer mit einer neuen IP die Seite besucht oder es muss bei einem bestehenden Eintrag das Datum aktualisieren, falls der User mit der IP-Adresse schon in der Tabelle steht. Das heißt wir brauchen eine Fall-Unterscheidung mit der wir dann entweder ein INSERT oder ein UPDATE Befehl ausführen. Dann müssen wir ausgeben wieviele Einträge in der Datenbank sind. Das ist dann unser User Online Zahl. Als letzes müssen wir dann ein MySQL-Befehl finden, der alle Datensätze, die schon zu lange in der Tabelle sind, löscht. Sonst würden ja immer mehr Datensätze in die Tabelle kommen und die Zahl, die ausgegeben wird, wird immer größer.
4. Das PHP-Script
Erstmal brauchen wir eine If-Abfrage die entweder ein INSERT oder ein UPDATE Befehl ausführt. Nur was nehmen wir als If-Bedingung? Wir müssen erstmal auslesen, ob in der Tabelle schon ein Datensatz mit der IP-Adresse des Users vorhanden ist oder nicht. Wir benutzen deswegen folgenden MySQL-Query.
SELECT COUNT(*) as Anzahl FROM Online WHERE IP = 'die-ip-adresse';
Der Ausdruck COUNT(*) zählt die Anzahl der Einträge in der Ergebnistabelle. Um den Wert dann auszulesen benutzen wir einen Alias. In PHP können wir dann über $row['Anzahl'] darauf zugreifen. Wenn wir keinen Alias benutzen müssten wir über $row['COUNT(*)'] darauf zugreifen.
Mit der WHERE-Bedingung geben wir wieder an, welche Datensätze wir haben wollen. COUNT(*) zählt dann nur die Datensätze, wo die Bedingung zutrifft. In der Spalte 'Anzahl' steht dann entweder 0, was heißt, dass kein Datensatz mit dieser IP gefunden wurde, oder eine 1. Dies ist also ideal für eine If-Abfrage.
<?php
$sql = "SELECT
COUNT(*) as Anzahl
FROM
Online
WHERE
IP = 'die-ip-adresse'";
$result = mysql_query($sql) OR die(mysql_error());
$row = mysql_fetch_assoc($result);
if($row['Anzahl']) {
// Nur Datum Updaten
} else {
// Neuer eintrag
}
?>
Nur was schreibt man für die IP-Adresse? In PHP gibt es ein Array $_SERVER. Im Array mit dem Index REMOTE_ADDR steht die IP-Adresse des Users der die Seite geöffnet hat. Diese können wir in den MySQL-Query verwenden.
<?php
$sql = "SELECT
COUNT(*) as Anzahl
FROM
Online
WHERE
IP = '".$_SERVER['REMOTE_ADDR']."'";
$result = mysql_query($sql) OR die(mysql_error());
$row = mysql_fetch_assoc($result);
if($row['Anzahl']) {
// Nur Datum Updaten
} else {
// Neuer eintrag
}
?>
Im If-Teil senden wir ein Query, der nur das Datum updated. Um im else-Teil ein Query, der einen neuen Eintrag hinzufügt.
<?php
$sql = "SELECT
COUNT(*) as Anzahl
FROM
Online
WHERE
IP = '".$_SERVER['REMOTE_ADDR']."'";
$result = mysql_query($sql) OR die(mysql_error());
$row = mysql_fetch_assoc($result);
if($row['Anzahl']) {
// Nur Datum Updaten
$sql = "UPDATE
Online
SET
Datum = NOW()
WHERE
IP = '".$_SERVER['REMOTE_ADDR']."'";
mysql_query($sql) OR die(mysql_error());
} else {
// Neuer eintra
$sql = "INSERT INTO Online
(IP, Datum)
VALUES
('".$_SERVER['REMOTE_ADDR']."', NOW())";
mysql_query($sql) OR die(mysql_error());
}
?>
Jetzt müssen wir auslesen, wieviele Datensätze insgesammt in der Tabelle sind. Es ist der selbe Befehl wie der erste, nur das die WHERE-Bedingung wegfällt.
<?php
$sql = "SELECT
COUNT(*) as Anzahl
FROM
Online
WHERE
IP = '".$_SERVER['REMOTE_ADDR']."'";
$result = mysql_query($sql) OR die(mysql_error());
$row = mysql_fetch_assoc($result);
if($row['Anzahl']) {
// Nur Datum Updaten
$sql = "UPDATE
Online
SET
Datum = NOW()
WHERE
IP = '".$_SERVER['REMOTE_ADDR']."'";
mysql_query($sql) OR die(mysql_error());
} else {
// Neuer eintra
$sql = "INSERT INTO Online
(IP, Datum)
VALUES
('".$_SERVER['REMOTE_ADDR']."', NOW())";
mysql_query($sql) OR die(mysql_error());
}
$sql = "SELECT
COUNT(*) as Anzahl
FROM
Online";
$result = mysql_query($sql) OR die(mysql_error());
$row = mysql_fetch_assoc($result);
echo "User Online: ".$row['Anzahl']."<br />";
?>
Jetzt brauchen wir noch ein Query, der die alten Datensätze löscht. Dabei müssen wir einmal wissen, wann ein Datensatz veraltet ist, damit er gelöscht werden kann. Als Timeout nehme ich mal 1 Minute. Und dann müssen wir noch wissen, wie wir löschen. Wir können erstmal den ersten Teil des DELETE-Befehls hinschreiben.
DELETE FROM Online
In MySQL gibt es die Zeit-Funktionen DATE_ADD() und DATE_SUB(). Mit denen können wir zu einem Datum eine Zeitspanne addieren bzw. von einem Datum eine Zeitspanne subtrahieren. Wir benutzen in diesem Fall die Funktion DATE_SUB(). Als 1. Parameter muss man ein Datum oder eine Spalte angeben von der man ein Zeitinterval abziehen möchte. Als 2. Parameter gibt man das Zeitinterval an.
Wir ziehen vom Aktuellen Zeitdruck (NOW()) eine Minute ab. Dieser Wert muss dann größer sein als der Wert in der Spalte, damit der Datensatz gelöscht wird. Der fertige Query wird dann so aussehen.
DELETE FROM Online WHERE DATE_SUB(NOW(), INTERVAL 1 MINUTE) > Datum;
MySQL zieht hier vom Rückgabewert von NOW() eine Minute ab und vergleicht es mit der Spalte Datum. Wenn dieser Wert größer ist als der Wert in der Spalte wird der Datensatz gelöscht. Siehe auch 16.7. Wie lösche ich alle Datensätze, die älter als n Tage sind? aus der de.comp.lang.php FAQ.
Diesen Query schicken wir nun an die Datenbank. Dies machen wir bevor wir die Anzahl der Datensätze auslesen. Somit stellen wir sicher, dass wir auch wirklich nur die Anzahl ausgeben, die auch wirklich in der Datenbank sind. Würden wir erst auslesen und dann löschen kann es sein dass die Angabe gefälscht ist (das ist sie zwar sowieso ;)). Denn wenn z.B. 10 Datensätze in der Datenbank sind, die schon bei weitem veraltet sind, würde der SELECT COUNT(*) Befehl diese ja auch erfassen und mit berechnen. Bei stark besuchten Seiten fällt das nicht auf, aber bei wenig besuchten Seiten schon. Deswegen löschen wir erst alle alten Datensätze und zählen dann nur noch den Rest in der Datenbank.
<?php
$sql = "SELECT
COUNT(*) as Anzahl
FROM
Online
WHERE
IP = '".$_SERVER['REMOTE_ADDR']."'";
$result = mysql_query($sql) OR die(mysql_error());
$row = mysql_fetch_assoc($result);
if($row['Anzahl']) {
// Nur Datum Updaten
$sql = "UPDATE
Online
SET
Datum = NOW()
WHERE
IP = '".$_SERVER['REMOTE_ADDR']."'";
mysql_query($sql) OR die(mysql_error());
} else {
// Neuer eintra
$sql = "INSERT INTO Online
(IP, Datum)
VALUES
('".$_SERVER['REMOTE_ADDR']."', NOW())";
mysql_query($sql) OR die(mysql_error());
}
// alte Datensätze löschen
$sql = "DELETE FROM
Online
WHERE
DATE_SUB(NOW(), INTERVAL 1 MINUTE) > Datum";
mysql_query($sql) OR die(mysql_error());
// Anzahl Ausgeben
$sql = "SELECT
COUNT(*) as Anzahl
FROM
Online";
$result = mysql_query($sql) OR die(mysql_error());
$row = mysql_fetch_assoc($result);
echo "User Online: ".$row['Anzahl']."<br />";
?>
Somit ist uns Script fertig. Dies includen wir in der index.php an einer beliebige Stelle. Oben im Header/Banner macht man dies üblicherweise.
Fragen zum aktuellen Thema
- Was macht die MySQL-Funktion DATE_ADD/SUB
-
Diese Funktion liefert ein Datum zurück, welches um ein bestimmtes Zeitinterval von einem übergebenen Datum verschoben ist. Weitere Infos dazu im MySQL-Manual zu DATE_ADD/SUB.
- Was macht die MySQL-Funktion COUNT(*)
-
Diese Funktion zählt die Anzahl der Datensätze in der Resulttabelle. Der Wert ist abhängig von der WHERE-Bedingung. Mit der Angabe von GROUP BY arbeitet diese Funktion etwas anders.