Mr_T: Besucherzähler in PHP Nr.2

Hi ich bin es nochmal euer Mr_T :-)

manche erinnern sich vielleicht noch an mein erstes Thema zu einem Besucherzähler.

Jetzt bin ich auf der seite eines bekannten auf einen Besucherzähler gestoßen der mir noch besser gefällt. Allerdings verstehe ich nicht wie dieser funktioniert.....

das ist die seite:
http://v-i-productions.dreipage.de/home_13691211.html

und im quelltext interessiert mich diese zeile:
<font size="5"><br /><br /><br /><br /><br /><br /><br /><br /><br /><font size="3">Diese Webseite hatte bereits <span style="color: rgb(0, 0, 255);"><script language="javascript" src="counter.php?art=gesamt"></script></span> Besucher. Heute haben <span style="color: rgb(255, 102, 0);"><script language="javascript" src="counter.php?art=tag"></script> </span>Leute diese Seite besucht.</font><br /></font></div>

kann mir jemand diese Vorgehensweise erklären???

ps.: wie erstelle ich zu alten narichten im archiv noch antworten???

gruß der
          Mr_T

  1. Hi,

    Hi ich bin es nochmal euer Mr_T :-)

    manche erinnern sich vielleicht noch an mein erstes Thema zu einem Besucherzähler.

    Ja.

    Jetzt bin ich auf der seite eines bekannten auf einen Besucherzähler gestoßen der mir noch besser gefällt. Allerdings verstehe ich nicht wie dieser funktioniert.....

    das ist die seite:
    http://v-i-productions.dreipage.de/home_13691211.html

    und im quelltext interessiert mich diese zeile:

    Diese Webseite hatte bereits
    <script language="javascript" src="counter.php?art=gesamt"></script>

    Hier wird counter.php eingebunden, mit dem Wert gesamt. Damit gibt counter.php ein Javascript aus, dass die Gesamtzahl der Besucher anzeigt.

    Heute haben <script language="javascript" src="counter.php?art=tag"></script>

    Hier wird es mit dem Wert tag aufgerufen, damit werden wohl die Besucher des aktuellen Tages angezeigt.

    kann mir jemand diese Vorgehensweise erklären???

    Das zählen wird von dem PHP-Script übernommen. Je nach Parameter gibt es dann den gewünschten Wert zurück.
    counter.php?art=gesamt gibt "document.write('1799');" zurück. Damit wird an die Stelle an der das Script eingebunden wird "1799" geschrieben.
    Das gleiche ist es bei "art=tag", nur dass da eine andere Zahl zurückgegeben wird.

    ps.: wie erstelle ich zu alten narichten im archiv noch antworten???

    Das geht garnicht. Du kannst nur ein neues Posting erstellen und dich mit einem Link auf das alte Posting beziehen.

    mfG,
    steckl

  2. kann mir jemand diese Vorgehensweise erklären???

    Es gibt ein PHP-Script auf dem Server namens counter.php, welches die Besucher zählt. Auf Anfrage liefert es seine Ergebnisse in Form einer JavaScript-Anweisung a la document.write('42'), weshalb im HTML drumherum die script-Tags stehen.

    Für weitere Details frage doch einfach Deinen Bekannten.

    ps.: wie erstelle ich zu alten narichten im archiv noch antworten???

    Das ist nicht möglich, wenn Du ein archiviertes Thema wieder aufgreifen willst, musst Du ein neues Posting absetzen. Es wäre zusätzlich hilfreich, wenn Du den archivierten Thread verlinkst, damit man nicht alles nochmal durchkaut, was bereits geklärt ist.

    Siechfred

    --
    Obacht, hinter jedem noch so kleinen Busch könnte ein Indianer sitzen!
  3. ok, was den "bekannten" betrifft: ich habe extra nicht freund geschrieben, da er mir NICHT(!) helfen würde einen derartigen besucherzähler auf meiner Seite einzubauen.

    Mein aktueller Besucherzähler sieht so aus:

    Hier die counter.php die beim seitenaufruf aufgerufen wird:

    <?  
    $aktiv = 1;  
    $zeit = 1;  
    $ipdatei = "ips.log";  
    $datei = "counter.dat";  
    $vdatei = "vdatei.dat";  
    $stellen = 5;  
      
    function check_IP($rem_addr) {  
    global $ipdatei,$zeit;  
    @$ip_array = file($ipdatei);  
    $reload_dat = fopen($ipdatei,"w");  
    $this_time = time();  
    for ($i=0; $i<count($ip_array); $i++) {  
    list($ip_addr,$time_stamp) = explode("|",$ip_array [$i]);  
    if ($this_time < ($time_stamp+60*$zeit)) {  
    if ($ip_addr == $rem_addr) {  
    $gefunden=1;  
    }  
    else {  
    fwrite($reload_dat,"$ip_addr|$time_stamp");  
    }  
    }  
    }  
    fwrite($reload_dat,"$rem_addr|$this_time\n");  
    fclose($reload_dat);  
    return ($gefunden==1) ? 1 : 0;  
    }  
    if (file_exists($datei) && ($aktiv==0 || ($aktiv==1 &&  
    check_IP($REMOTE_ADDR)==0))) {  
    $fpv=fopen($vdatei,"r+");  
    $fp=fopen($datei,"r+");  
    $zahl=fgets($fp,$stellen);  
    $zahl++;  
    rewind($fp);  
    flock($fp,2);  
    fputs($fp,$zahl,$stellen);  
    fputs($fpv,"var Counter = 'Besucher: 000".$zahl."';");  
    flock($fp,3);  
    fclose($fp);  
    } else {  
    $fp=fopen($datei,"r");  
    $zahl=fgets($fp,$stellen);  
    fclose($fp);  
    }  
    $zahl=sprintf("%0".$stellen."d",$zahl);  
    ?> 
    

    counter.dat:
    23

    vdatei.dat: (der inhalt dieser datei wird dann auf meiner website angezeigt...)
    var Counter = 'Besucher: 00023';

    Diese Methode geht zwar, ist jedoch erstens umständlich und zweitens nicht so gut wie die andere.

    Nun hätte ich gerne gewusst was in der counter.php drinsteht und wieso es so einfach geht (mit scr=counter.php?art=tag....).

    gruß der Mr_T

    1. Hello,

      Spätens mit der nächsten Zeile wir es unsauber:

      if (file_exists($datei) && ($aktiv==0 || ($aktiv==1 &&

      ein separates file_exists() auf eine Datei, die dann erst einite Momemte später geöffnet wird, ist keine wirkliche Lösung. Zwischen die "Prüfung" und die Sperre passen mindestens drei Omnibusse

      check_IP($REMOTE_ADDR)==0))) {
      $fpv=fopen($vdatei,"r+");

      spätestens hier muss die Datei auch exclusiv gesperrt werden

      $fp=fopen($datei,"r+");
      $zahl=fgets($fp,$stellen);
      $zahl++;
      rewind($fp);
      flock($fp,2);

      Das exclusive Sperren ist hier zu spät.
      Benutze zum Sperren außerdem die Konstanten, die dafür vorgesehen sind

      • LOCK_EX
      • LOCK_SH
      • LOCK_UN  (was Du aber im Normalfall nie benötigst)

      fputs($fp,$zahl,$stellen);
      fputs($fpv,"var Counter = 'Besucher: 000".$zahl."';");
      flock($fp,3);

      Ein Unlock ist hier falsch, wenn Du nicht vorher ein fflush() durchgeführt hast!

      fclose($fp);

      Besser ist es, die Datei nur zu schließen.
      Dadurch wird sie erst geflusht und dann geschlossen und die Sperre entfernt.

      } else {
      $fp=fopen($datei,"r");

      Heru wäre dann aber ein LOCK_SH angebracht, nicht dass mitten im Auslesen die Datei beschrieben wird.

      Ich bin mir zwar nicht sicher, wie PHP die Stream-Direktiven von POSIX umsetzt (insbesondere auf Windows, da muss das ja "frei übrsetzt" werden), aber besser ist es, ein sauberes Programm zu schreiben.

      Anderenfalls würden die Streams die Atomarisierung der Lese- und der Schreibprozesse steuern.
      Da Du nur zum Zwecke des Anzeigens auslesen willst, wäre es egal, ob sich sofort nach dem Auslesen der Datei der Inhalt ändert, eventuell sogar noch bevor Du ihn angezeigt hast.

      Liebe Grüße aus Syburg bei Dortmund

      Tom vom Berg

      --
      Nur selber lernen macht schlau
      http://bergpost.annerschbarrich.de
      1. Lieber Tom,

        Ich bin mir zwar nicht sicher, wie PHP die Stream-Direktiven von POSIX umsetzt (insbesondere auf Windows, da muss das ja "frei übrsetzt" werden), aber besser ist es, ein sauberes Programm zu schreiben.

        Beim Einsatz von multithreaded Webservern, wie z.B. den IIS mit ISAPI unter Windows, funktioniert flock() nicht zuverlässig. Ich kann dir also nur zustimmen: Man sollte unbedingt darauf achten, keine Race Conditions einzubauen.

        1. Hello Christoph,

          Ich bin mir zwar nicht sicher, wie PHP die Stream-Direktiven von POSIX umsetzt (insbesondere auf Windows, da muss das ja "frei übrsetzt" werden), aber besser ist es, ein sauberes Programm zu schreiben.

          Beim Einsatz von multithreaded Webservern, wie z.B. den IIS mit ISAPI unter Windows, funktioniert flock() nicht zuverlässig. Ich kann dir also nur zustimmen: Man sollte unbedingt darauf achten, keine Race Conditions einzubauen.

          Auf IIS würd man doch aber wohl eher asp.net benutzen und nicht php. Oder kostet die Benutzung der Microsoft-Lösung auf einem gefauften IIS noch etwas extra?

          Dass man zum Anwenden von .net erst einen Doktor machen muss, ist natürlich klar :-)

          Liebe Grüße aus Syburg bei Dortmund

          Tom vom Berg

          --
          Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de
          1. Hallo,

            Auf IIS würd man doch aber wohl eher asp.net benutzen und nicht php.

            Naja, diese Kombination gibt es wohl schon gelegentlich. Man kann PHP ja auch innerhalb des .Net-Frameworks verwenden. Warum man das auch immer wollen sollte ...

            Oder kostet die Benutzung der Microsoft-Lösung auf einem gefauften IIS noch etwas extra?

            Nein, aber die üblichen Entwicklungsumgebungen für .Net schon.

            Dass man zum Anwenden von .net erst einen Doktor machen muss, ist natürlich klar :-)

            Schön wärs.

            Das Problem dürfte übrigens auch dann auftreten, wenn man einen Worker-Apache mit PHP unter Windows verwendet. Insgesamt sollte man IMHO auf Locking im Dateisystem überhaupt nicht bauen, sondern in solchen Fällen eine Datenbank mit Transaktionen verwenden.

            Gruß
            Christoph, der Counter für sinnlos hält

        2. Hallo,

          Beim Einsatz von multithreaded Webservern, wie z.B. den IIS mit ISAPI unter Windows, funktioniert flock() nicht zuverlässig.

          Das ist übrigens falsch. Unter Windows funktionieren Locks, die mit LockFileEx() erzeugt wurden, auf Dateideskriptorebene, damit lassen sich problemlos verschiedene Threads gegeneinander abschotten. Selbst wenn ein Webserver nur Multiplexing betreiben würde und die Ausführung zwischen verschiedenen Threads hin- und herschieben würde (gut, das funktioniert mit PHP im Moment grundsätzlich nicht, aber spinnen wir mal den Gedankn weiter), selbst dann würde LockFileEx() unter Windows keine Probleme machen. Und PHP verwendet unter Windows LockFileEx() um flock() zu simulieren.

          Ich habe das auch schon selbst getestet, als ich für meinen Artikel zu Dateisperren recherchiert habe.

          [Es ist übrigens interessant, dass die Windows-Lösung die sauberste ist: Sie funktioniert auf Dateideskriptorebene und ist damit threadsicher, kann dafür auch nur bestimmte Dateibereiche sperren und funktioniert sogar über das Netzwerk. All diese Eigenschaften zusammen bietet keine der UNIX-Lösungen, nur immer eine Auswahl davon.]

          Viele Grüße,
          Christian

    2. Hi,

      Diese Methode geht zwar, ist jedoch erstens umständlich und zweitens nicht so gut wie die andere.

      zum einen kannst Du gar nicht wissen, ob die andere Methode nicht noch umständlicher als Deine ist, wenn Du das dahinter liegende PHP-Script nicht kennst und zum anderen ist die Nutzung von Javascript hierfür nicht so gut, denn es werden nur Besucher mit aktiviertem Javascript gezählt und die übrigen sehen dann die tolle Anzeige:
      "Diese Webseite hatte bereits Besucher. Heute haben Leute diese Seite besucht."
      *g* nette Formulierung und sogar zutreffend, da mindestens ein Besucher (ich) drauf war.

      Einen Vorteil hat das andere Script allerdings doch ggü. Deinem: es zählt keine Suchmaschinen-Bots.

      freundliche Grüße
      Ingo