<?php
/**
* Besucher-Zähler
*
* Der Counter zählt die Besucher (= Aufrufe jeder Seite) in
* zwei Tabellen: In der großen Tabelle werden alle Aufrufe
* über den gesamten Zeitraum gesichert (Archiv), in der
* kleinen Tabelle sind nur die letzten 10.000 Besucher
* enthalten. Dies ist notwendig, um die aktuelle Statistik
* (z.B. "Besucher heute" oder "Besucher in dieser Woche")
* nicht immer auf Basis der auf Dauer riesig werdenden
* Tabelle erstellen zu müssen (SQL-Performance).
*
* Zu jedem Hit wird nur die IP und die Aufrufzeit
* gespeichert. Mit Hilfe von $cfg['reload_time'] kann (in
* Sekunden) angegeben werden, ab welchem Abstand einer
* zweiter Seitenaufruf als neuer Besucher gewertet werden
* soll.
*/
abstract class Counter
{
// ===========================================================================
// SCHNITTSTELLE
// ===========================================================================
/**
* Diese Methode zählt einen Aufruf von
* einer $ip. Sie kümmert sich selber um die
* Ablaufzeit, darum, den Eintrag in beiden
* Tabellen einzufügen und ggf. auch den Tages-
* wechsel zu beachten.
*
* Da die Methode in der Regel aufgerufen wird,
* ohne dass ein MySQL-Objekt besteht, nutzt sie
* die mysql_*-Funktionen von PHP direkt.
*
* @param string $ip die IP des Besuchers
* @param resource $sqlConnection die zu verwendende Datenbank-Verbindung
*/
public static function countHit($ip,$sqlConnection)
{
if(DEBUG) Debug::checkArguments(__METHOD__,"sr",$ip,$sqlConnection);
// In der Regel ist beim Aufruf von countHit
// noch keine Registry vorhanden, daher würde
// ein Registry::get("cfg") nichts bringen.
global $cfg;
$_now = time();
$_today = mktime(0,0,0,date('n'),date('j'),date('Y'));
$now_mysql = strftime("%Y-%m-%d %H:%M:%S");
$max = strftime("%Y-%m-%d %H:%M:%S",time()-4*ONE_DAY);
// Prüfen, ob diese IP bereits in der DB vorhanden ist.
$result = mysql_query("SELECT UNIX_TIMESTAMP(hit) AS hit FROM ".TBL_COUNTER_RECENT." WHERE hit >= '$max' AND ip = '$ip' ORDER BY hit DESC",$sqlConnection);
// Möglichkeit 1: nicht gefunden -> neuer Besucher
// Möglichkeit 2: gefunden, aber alt -> neuer Besucher
// Möglichkeit 3: gefunden, aktuell -> kein neuer Besucher
// Und dann müssen wir noch unterscheiden: wenn gefunden:
// a) von heute, dann aktualisieren
// b) nicht von heute, dann neuen Eintrag
if ( !$result || mysql_num_rows($result) == 0 ) // nicht gefunden
{
mysql_query("INSERT INTO ".TBL_COUNTER_RECENT." (ip,hit) VALUES ('$ip','$now_mysql')",$sqlConnection);
mysql_query("INSERT INTO ".TBL_COUNTER." (ip,hit) VALUES ('$ip','$now_mysql')",$sqlConnection);
}
else // gefunden
{
$hit = mysql_fetch_row($result);
$hit = intval($hit[0]);
if ( $hit < $_today ) // letzter Besuch war GESTERN
{
mysql_query("INSERT INTO ".TBL_COUNTER_RECENT." (ip,hit) VALUES ('$ip','$now_mysql')",$sqlConnection);
mysql_query("INSERT INTO ".TBL_COUNTER." (ip,hit) VALUES ('$ip','$now_mysql')",$sqlConnection);
}
else // letzter Besuch dieser IP war HEUTE
{
if ( $_now - $hit > $cfg['reload_time'] ) // neuer Besucher
{
mysql_query("INSERT INTO ".TBL_COUNTER_RECENT." (ip,hit) VALUES ('$ip','$now_mysql')",$sqlConnection);
mysql_query("INSERT INTO ".TBL_COUNTER." (ip,hit) VALUES ('$ip','$now_mysql')",$sqlConnection);
}
else
{
// NUR DEN AKTUELLSTEN EINTRAG AKTUALISIEREN (!!!)
$result = mysql_query("SELECT hit FROM ".TBL_COUNTER_RECENT." WHERE ip = '$ip' AND DAYOFYEAR(hit) = DAYOFYEAR(NOW()) ORDER BY hit DESC",$sqlConnection);
$hit = mysql_fetch_row($result);
$hit = $hit[0];
mysql_query("UPDATE ".TBL_COUNTER_RECENT." SET hit = '$now_mysql' WHERE ip = '$ip' AND hit = '$hit' LIMIT 1",$sqlConnection);
mysql_query("UPDATE ".TBL_COUNTER." SET hit = '$now_mysql' WHERE ip = '$ip' AND hit = '$hit' LIMIT 1",$sqlConnection);
}
}
}
}
/**
* Diese Methode löscht, falls die Mini-Tabelle
* mehr als 10.000 Einträge enthält, alle Aufrufe,
* die älter als 5 Tage sind. Es ist also
* sichergestellt, dass in der kleinen Tabelle
* immer die Daten der letzten 5 Tage enthalten
* sind.
*
* @param resource $sqlConnection die zu verwendende Datenbank-Verbindung
*/
public static function truncateRecent($sqlConnection)
{
if(DEBUG) Debug::checkArguments(__METHOD__,"r",$sqlConnection);
$result = mysql_query("SELECT COUNT(*) FROM ".TBL_COUNTER_RECENT,$sqlConnection);
$result = mysql_fetch_row($result);
if ( $result[0] > 10000 )
{
$now = strftime("%Y-%m-%d %H:%M:%S",time()-5*ONE_DAY);
mysql_query("DELETE FROM ".TBL_COUNTER_RECENT." WHERE hit <= '$now'",$sqlConnection);
}
}
}
?>
Snippetdetails
- hinzugefügt: 27.09.2008
- aktualisiert: 27.09.2008
- Snippet herunterladen
Kommentar verfassen
Fehler gefunden? Doofer Code? Ein kleines "Danke!"? Hinterlasse einfach einen Kommentar.
Dein Kommentar wird erst nach einer manuellen Prüfung angezeigt.