PHP Besucherzähler

Status
Für weitere Antworten geschlossen.

Felidae

New member
Hallo, ich habe einen Besucherzähler geschrieben und für alle die selbst einen schreiben möchten oder einfach einen zum Übernehmen brauchen stelle ich ihn hier mit Erklärung zur Verfügung.

Er soll jeden Besucher zählen (kein Botschutz usw.) aber das nur einmal pro Tag. Der selbe Besucher wird also erst nach 0 Uhr wieder gezählt. Das ganze funktioniert mit einer IP Kontrolle.

In einer MySQL Datenbank speichern wir alle Notwendigen Daten.
Code:
Besucher
    Besucher_ID (int, auto_increment, Primärschlüssel)
    Besucher_Datum (date)
    Besucher_IP (varchar 39)
Besucher_ID: Eine fortlaufende Nummerierung aller Gäste.
Besucher_Datum: Speichert das Datum des Besuchers.
Besucher_IP: Die IP das Besuchers.

Zuerst beginnen wir das PHP Script, lassen uns alle Fehler anzeigen und senden einen header. Anschließend muss noch die Verbindung zum Server und zur Datenbank aufgenommen werden.
PHP:
<?php
    error_reporting(E_ALL);
    header("Content-Type: text/html; charset=utf-8");
    mysql_connect("localhost", "name", "passwort") OR die("Verbindung zum Server konnte nicht aufgebaut werden.\n");
    mysql_select_db("datenbank") OR die("Verbindung zur Datenbank konnte nicht aufgebaut werden.\n");

Da wir nach 0 Uhr den Besucher wieder zählen möchten, müssen die Einträge die nicht von heute sind gelöscht werden. Dazu senden wir einen Query, der genau dies tut.
PHP:
    $query = "DELETE FROM
                  Besucher
              WHERE
                  Besucher_Datum != CURDATE();";
    mysql_query($query) OR die("Daten konnten nicht übertragen werden.\n");

Jetzt wenden wir uns dem aktuellen Besucher zu und überprüfen erstmal, ob seine IP schon in der Datenbank steht. Dazu senden wir einen Query der alle Einträge aus der Datenbank holt die die selbe IP haben wie der aktuelle Besucher.
PHP:
    $query = "SELECT
                  Besucher_IP
              FROM
                  Besucher
              WHERE
                  Besucher_IP = '".$_SERVER['REMOTE_ADDR']."';";
    $result = mysql_query($query) OR die("Daten konnten nicht übertragen werden.\n");

Wenn wir diese Anzahl jetzt von der Funktion mysql_num_rows() durchzählen lassen, erhalten wir entweder 1 oder 0, da die IP entweder schon da ist oder eben nicht. Das überprüfen wir mit einer If-Abfrage und wenn die IP noch nicht in der Datenbank steht fügen wir sie mit dem aktuellen Datum hinzu.
PHP:
    if(mysql_num_rows($result) == 0) {
        $query = "INSERT INTO
                      Besucher
                  SET
                      Besucher_Datum = NOW(),
                      Besucher_IP = '".$_SERVER['REMOTE_ADDR']."';";
        mysql_query($query) OR die("Daten konnten nicht übertragen werden.\n");
    }

Auf der Seite möchten wir nacher ausgeben wie viele Besucher heute und wie viele schon insgesamt auf der Seite waren. Dazu benutzen wir die beiden Variaben $heute und $gesamt.

Um die Variable $heute zu füllen zählen wir einfach alle Einträge in der Datenbank durch, denn da wir ganz am Anfang alle älteren gelöscht haben sind jetzt nur noch die heutigen darin.
PHP:
    $query = "SELECT
                  Besucher_ID
              FROM
                  Besucher;";
    $result = mysql_query($query) OR die("Daten konnten nicht übertragen werden.\n");
    $heute = mysql_num_rows($result);

Die Variable $gesamt füllen wir, indem wir die größte Besucher_ID auslesen. Denn da ja alle Besucher fortlaufend nummeriert werden sagt uns die neuste ID auch wie viele Besucher insgesamt da waren.
PHP:
    $query = "SELECT
                  Besucher_ID
              FROM
                  Besucher
              ORDER BY
                  Besucher_ID DESC
              LIMIT
                  1;";
    $result = mysql_query($query) OR die("Daten konnten nicht übertragen werden.\n");
    $row = mysql_fetch_assoc($result);
    $gesamt = $row['Besucher_ID'];

Jetzt müssen wir das nur noch mit HTML auf die Seite schreiben lassen und das PHP Script beenden.
PHP:
    echo "<?xml version='1.0' encoding='utf-8' ?>\n";
    echo "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.1//EN' 'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd'>\n";
    echo "<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='de'>\n";
    echo "    <head>\n";
    echo "        <title>Besucherzähler</title>\n";
    echo "        <meta name='robots' content='noindex, nofollow' />\n";
    echo "    </head>\n";
    echo "    <body>\n";
    echo "        <table border='1'>\n";
    echo "            <tr>\n";
    echo "                <th colspan='2'>Besucher</th>\n";
    echo "            </tr>\n";
    echo "            <tr>\n";
    echo "                <td>Heute</td>\n";
    echo "                <td>$heute</td>\n";
    echo "            </tr>\n";
    echo "            <tr>\n";
    echo "                <td>Gesamt</td>\n";
    echo "                <td>$gesamt</td>\n";
    echo "            </tr>\n";
    echo "        </table>\n";
    echo "    </body>\n";
    echo "</html>\n";
?>


Das ist schon der komplette Besucherzähler. Der folgende Code beinhaltet nochmal alles am Stück und ist damit nichts neues mehr.

PHP:
<?php
    error_reporting(E_ALL);
    header("Content-Type: text/html; charset=utf-8");
    mysql_connect("localhost", "name", "passwort") OR die("Verbindung zum Server konnte nicht aufgebaut werden.\n");
    mysql_select_db("datenbank") OR die("Verbindung zur Datenbank konnte nicht aufgebaut werden.\n");
    // Alte IP-Adressen löschen
    $query = "DELETE FROM
                  Besucher
              WHERE
                  Besucher_Datum != CURDATE();";
    mysql_query($query) OR die("Daten konnten nicht übertragen werden.\n");
    // Wenn aktuelle IP nicht vorhanden, dann in die DB eintragen
    $query = "SELECT
                  Besucher_IP
              FROM
                  Besucher
              WHERE
                  Besucher_IP = '".$_SERVER['REMOTE_ADDR']."';";
    $result = mysql_query($query) OR die("Daten konnten nicht übertragen werden.\n");
    if(mysql_num_rows($result) == 0) {
        $query = "INSERT INTO
                      Besucher
                          (Besucher_Datum,
                           Besucher_IP)
                  VALUES
                      (NOW(),
                       '".$_SERVER['REMOTE_ADDR']."');";
        mysql_query($query) OR die("Daten konnten nicht übertragen werden.\n");
    }
    // IP-Adressen durchzählen und größte ID auslesen
    $query = "SELECT
                  Besucher_ID
              FROM
                  Besucher;";
    $result = mysql_query($query) OR die("Daten konnten nicht übertragen werden.\n");
    $heute = mysql_num_rows($result);
    $query = "SELECT
                  Besucher_ID
              FROM
                  Besucher
              ORDER BY
                  Besucher_ID DESC
              LIMIT
                  1;";
    $result = mysql_query($query) OR die("Daten konnten nicht übertragen werden.\n");
    $row = mysql_fetch_assoc($result);
    $gesamt = $row['Besucher_ID'];
    // Ausgabe in HTML
    echo "<?xml version='1.0' encoding='utf-8' ?>\n";
    echo "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.1//EN' 'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd'>\n";
    echo "<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='de'>\n";
    echo "    <head>\n";
    echo "        <title>Besucherzähler</title>\n";
    echo "        <meta name='robots' content='noindex, nofollow' />\n";
    echo "        <meta http-equiv='Content-Style-Type' content='text/css' />\n";
    echo "        <link rel='stylesheet' type='text/css' href='style.css' />\n";
    echo "    </head>\n";
    echo "    <body>\n";
    echo "        <table border='1'>\n";
    echo "            <tr>\n";
    echo "                <th colspan='2'>Besucher</th>\n";
    echo "            </tr>\n";
    echo "            <tr>\n";
    echo "                <td>Heute</td>\n";
    echo "                <td>$heute</td>\n";
    echo "            </tr>\n";
    echo "            <tr>\n";
    echo "                <td>Gesamt</td>\n";
    echo "                <td>$gesamt</td>\n";
    echo "            </tr>\n";
    echo "        </table>\n";
    echo "    </body>\n";
    echo "</html>\n";
?>

Ich hoffe, dass mein Tutorial einigermaßen hilfreich und verständlich war.
mfg.
 
Zuletzt bearbeitet:
mhh, ich geb mal ein bissel Kritik ab
warum löschst du denn die alten Einträge?
du könntest stattdessen einfach bei der überprüfung ob die IP schon existiert, einfach das Datum mit überprüfen lassen... dann könnte man wenigstens Statistiken über andere Tage als den aktuellen machen...

Das nächste negative:jeder deiner Besucher ruft diesen DELETE-query auf...
ja so ein Befehl wird schnell abgearbeitet... aber wenn du z.B. 10.000 Besucher am Tag hast fällt auch das ins Gewicht

ich will dein Tutorial nicht schlecht reden, aber vielleicht sollte noch ein bissel geschraubt werden ;) z.B. wäre noch eine Erweiterung, die Browser der Besucher auszulesen oder vielleicht noch das Betriebssystem....
und wenn du richtig lange weile hast, kannst noch eine Zuordnung der IP´s zu Regionen machen (wobei ich da selbst auch grad nicht wüsste wie das geht)

edit: kaum ein user hat 24Stunden lang die selbe IP, ein cookie hingegen wird von den meisten Internetnutzern nicht gelöscht, hierüber könnte man z.B. eine bessere Identifizierung machen
 
Zuletzt bearbeitet:
error_reporting(E_ALL); kann man für Entwicklungszwecke mal durchaus machen, wenn das ganze auf dem Server läuft sollte da aber nicht mehr als ein error_reporting(E_WARNING), besser noch eine eigener Errorhandler laufen.

Ansonsten würde ich die Serverlogfiles auswerten, statt selber zu zählen. Entsprechende Tools gibts zu hauf.
 
Hallo, ja Kritik ist kein Problem, aber ich versuche mal was dazu zu sagen. ^^

Ich lösche die alten Einträge, weil ansonsten irgendwann die DB sehr sehr voll wird. Und das muss ja nicht sein. Über andere Tage kann man die Statistik halt machen, wenn man das Script ein wenig abändert. Aber es war halt dafür gedacht. Sollte nur etwas kleines sein. Anpassen kann man es immer noch.

Und wenn ich daran festhalte lässt sich das mit dem DELETE Query leider nicht vermeiden. Muss ja immer überprüft werden wenn ich etwas löschen will. Und so viele Besucher sind es ja auch nicht. ^^ Ist das denn wirklich so dramatisch, mit dem DELETE Query? Weil mit dem jetzigen System geht das glaube ich nur so. Also wenn ich an der Funktionsweise festhalten möchte.

Das mit den Erweiterungen zur Statistik ist natürlich eine tolle Sache, aber auch viel Arbeit. Und für meinen Zweck hat erstmal so ein kleiner ausgereicht. Und ich denke für ein Tutorial ist das auch eher zu gebrauchen, oder?

Dass mit den IP's stimmt leider. Aber Cookies haben wiederum den Nachteil, dass manche Cookies sperren oder direkt löschen lassen. Dann würde der Counter auch sehr verfälscht werden. Eine Mischung wäre wohl am angebrachtesten, aber zur Zeit möcte ich mich nur ungern damit beschäftigen. ^^

Das mit dem ERROR_REPORTING ist auch wahr, aber nicht so wichtig finde ich. Wenn alles sauber programmiert ist sollte es nicht zu Fehlern kommen und wenn diese vom Server kommen ist es ja auch nicht schlimm, wenn diese angezeigt werden.

Aber das mit dem auslesen der Serverlogfiles finde ich interessant. Wo liegen da die Vorteile, wie lese ich diese aus und wie zähöt das Ding? Mit Reload Sperre? Ist das auch für einzele Unterordner möglich? Weil meine HPs liegen für gewöhnlich in einem Unterordner.

mfg.
 
Ich lösche die alten Einträge, weil ansonsten irgendwann die DB sehr sehr voll wird.
Dafür sind ja Datenbanken da, so nen paar 100 Einträge kann man auch noch in ner text-Datei verwalten. Mit den richtigen Indexen sollten nen paar Millionen auch kein Problem sein. Und falls die Abfragen für Besucher-Gesamt-Heute zu langsam werden kann man das durch redundantes Speichern noch umgehen (indem man die Anzahl extra speichert und mit jedem neuen Besucher erhöht).

Und wenn ich daran festhalte lässt sich das mit dem DELETE Query leider nicht vermeiden.
Da das nur einmal am Tag passiert, wäre nen Cronjob besser geeignet.

Das mit dem ERROR_REPORTING ist auch wahr, aber nicht so wichtig finde ich. Wenn alles sauber programmiert ist sollte es nicht zu Fehlern kommen und wenn diese vom Server kommen ist es ja auch nicht schlimm, wenn diese angezeigt werden.
Fehlermeldungen die direkt vom Server kommen, können einem Angreifer potentielle Angriffspunkte liefern.

Aber das mit dem auslesen der Serverlogfiles finde ich interessant. Wo liegen da die Vorteile, wie lese ich diese aus und wie zähöt das Ding? Mit Reload Sperre? Ist das auch für einzele Unterordner möglich? Weil meine HPs liegen für gewöhnlich in einem Unterordner.
Apache log jeden Zugriff mit. Was da drin genau steht, ist wahrscheinlich Einstellungssache.

mal nen Beispiel
Code:
127.0.0.1 - - [27/Jun/2008:14:47:59 +0200] "GET /phpmyadmin/themes/original/img/b_ftext.png HTTP/1.1" 200 277
127.0.0.1 - - [27/Jun/2008:14:48:11 +0200] "POST /phpmyadmin/tbl_addfield.php HTTP/1.1" 200 5503
127.0.0.1 - - [27/Jun/2008:14:48:32 +0200] "POST /phpmyadmin/tbl_addfield.php HTTP/1.1" 200 3514
127.0.0.1 - - [27/Jun/2008:14:48:44 +0200] "POST /phpmyadmin/tbl_addfield.php HTTP/1.1" 200 5676
Direkten Zugriff wirst du wohl bei den meisten Hostern nicht haben, allerdings bieten dir viele schon vorinstallierte Tools an, um aus den Logfiles "vernünftige" Statistiken zu erhalten.
 
Zuletzt bearbeitet:
Hi, ok das mit den log files werde ich wohl nicht machen können. Das wird bei mir anscheinend nicht unterstützt. Kann ja nochmal nachgucken.

Aber wie sieht das mit dem Cronjob aus. Hab davon schon gehört, also es wird wohl etwas sein, dass in einem bestimmten Zeitintervall ausgeführt wird. Aber mehr weis ich nicht.
Ist das ne PHP Datei, wo muss sie liegen, wie markiert man sie als Cronjob usw. Könnte ich da noch ein wenig beraten werden? ^^

mfg.
 
cronjobs werden meist nur von professionellen Webhostern angeboten die auch ein bissel was kosten.... wie diese bei den einzelnen Providern eingestellt werden solltest du in den Manuals irgendwo finden, wenn du nen eigenen Unix-Server hast such mal nach "crontab", in diese Datei machst du die Einträge
 
es gibt im Netz auch kostenlose cronjobs. Da ruft dann ein anderere Server zu einem bestimmten Zeitpunkt(en) eine php Seite auf (o.ä.)
 
Status
Für weitere Antworten geschlossen.
Zurück
Oben