newbie: php mit txt.datei und abfragen

moin, ichbin newbie in php und hab da mal n paar fragen

ich möchte einen besucherzähler haben, der die ip des besuchers in eine textdatei untereinander schreibt.
z.b.:
127.0.0.1

das wars zum ersten.

das zweite:

nun soll php die ips vergleichen und die doppelten ips löschen und dabei aber die ip einmal bestehen lassen und dahinter die anzahl der aufrufe schreiben.

127.0.0.1
169.254.56.168
127.0.0.1

-->
127.0.0.1 2
169.254.56.168

so und das dritte:

php soll nun 2 ergebnisse präsentieren:

einmal die anzahl der insgesamten aufrufe 8inkl. alles doppelten aufrufe der selben ip)
und einmal nur die aufrufe von verschiedenen ips...

ich hoffe ihr könnt mir da helfen.

danke

  1. Hallo newbie,

    nun soll php die ips vergleichen und die doppelten ips löschen und dabei aber die ip einmal bestehen lassen und dahinter die anzahl der aufrufe schreiben.

    Beachte dabei, dass eine IP nicht unbedingt auch einem Benutzer entspricht. (deswegen mit Sessions o.ae. anzufangen halte ich aber für unnoetig, das sollte genau genug sein)
    Außerdem solltest du nach einer bestimmten Zeit (so ca. ein Tag) eine IP wieder zaehlen, weil das ja dann hoechstwahrscheinlich jemand anderes ist.

    Was ich speichern wuerde: IP, Anzahl der Aufrufe, Timestamp des letzten Aufrufs; also z.B. '127.0.0.1 5 1156188930'.

    Ich wuerde bei jedem Aufruf in der Datei nach dem letzten Vorkommen der IP suchen, gucken, ob der Timestamp weniger als 24h her ist, wenn ja den Zaehler erhoehen, wenn nein eine neue Zeile hinzufuegen.

    einmal die anzahl der insgesamten aufrufe inkl. alles doppelten aufrufe der selben ip)
    und einmal nur die aufrufe von verschiedenen ips...

    Fuer ersteres kannst du alle Anzahl-Werte raussuchen und zusammenrechnen, fuer zweiteres zaehlst du einfach die Zeilen der Datei.

    Viele Grüße aus Freiburg,
    Marian

    --
    Microsoft broke Volkswagen's world record: Volkswagen only made 22 million bugs!
    <!--[if IE]><meta http-equiv="refresh" content="0; URL=http://www.getfirefox.com"><[endif]-->
    1. hallo marian,

      also dann habe ich noch folgende newbie fragen:

      warum das datum so 1156188930 und nicht 21.08.06?
      wie funktioniert ein zeilenumbruch?

      $info = $ip." ".$datum."\n");

      so?
      ne oder?

      hast du eine formel für dei abfrage mit den 24 h bereit?
       danke für deine supi hilfe!

      1. hi,

        warum das datum so 1156188930 und nicht 21.08.06?

        Weil du einen Unix Timestamp für zahlreiche Berechnungen und Datumsaufbereitungen brauchen kannst, während du mit dem anderen Format sehr limitiert bist, und es immer erst wieder auseinanderpflücken und umwandeln müsstest, wenn du mal etwas anderes mit dem Datum vorhaben solltest.

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
      2. Hallo

        warum das datum so 1156188930 und nicht 21.08.06?

        Das erste ist der UNIX-Timestamp (Anzahl der Sekunden seit dem 01.01.1970, 00:00:00 Uhr). Mit dieser Angabe lässt sich mit den PHP Datums- und Zeitfunktionen rechnen. Mit der obigen deutschen Datumsangabe nicht. Die müsste erst maschinenverwertbar umgerechnet, der Rechenoperation unterzogen und wieder in das lesbare Format zurückportiert werden.

        Da ist es einfacher, in der Datei den verwertbaren Timestamp zu speichern, direkt mit ihm zu arbeiten und ihn nur zur Anzeige in das deutsche Format umzuwandeln.

        wie funktioniert ein zeilenumbruch?

        $info = $ip." ".$datum."\n");

        so?
        ne oder?

        Nee. Aber ohne die schließende Klammer gäb's ein: ja.

        Tschö, Auge

        --
        Die Musik drückt aus, was nicht gesagt werden kann und worüber es unmöglich ist zu schweigen.
        (Victor Hugo)
        Veranstaltungsdatenbank Vdb 0.1
        1. echo $begrüßung;

          Das erste ist der UNIX-Timestamp (Anzahl der Sekunden seit dem 01.01.1970, 00:00:00 Uhr).

          Ergänzend sei angemerkt, dass dem Unix-Timestamp immer UTC zugrunde liegt.

          echo "$verabschiedung $name";

      3. Hallo newbie,

        warum das datum so 1156188930 und nicht 21.08.06?

        Ich denke es ist einfacher mit einer Zahl als mit einem Datum (nur der Tag reicht IMHO nicht, weil wenn jemand um zehn vor zwoelf da draufgeht wird es um zehn nach zwoelf immernoch der gleiche sein).

        Die Zahl ist der UNIX-Timestamp, die Anzahl der Sekunden seit dem 1.1.1970. Den kriegst du einfach mit time(), und hinterher kannst du einfach gucken, ob der jetzige Timestamp minus der alte groesser als 24*60*60 ist.

        wie funktioniert ein Zeilenumbruch?

        Ich wuerde CRLF nehmen, also \r\n, das funktioniert auf allen Systemen.

        $info = $ip." ".$datum."\n");

        Klammer weg, Anzahl dazu, dann ja.

        hast du eine Formel für die Abfrage mit den 24 h bereit?

        Siehe oben, jetzt - vorher > 24*60*60

        Viele Grüße aus Freiburg,
        Marian

        --
        Microsoft broke Volkswagen's world record: Volkswagen only made 22 million bugs!
        <!--[if IE]><meta http-equiv="refresh" content="0; URL=http://www.getfirefox.com"><[endif]-->
        1. Hallo

          wie funktioniert ein Zeilenumbruch?
          Ich wuerde CRLF nehmen, also \r\n, das funktioniert auf allen Systemen.

          das ist falsch. Bitte lies den Artikel Plattformübergreifendes Handling von Zeilenumbrüchen.

          Wenn Du auf einer Unix-Maschine ein Perlskript mit Windowszeilenenden (sprich CRLF = Carriage Return, Linefeed oder Wagenrücklauf und Zeilenvorschub) verwendest, so gibt es Fehler. Es funktioniert nach meiner Erfahrung also _nicht auf allen_ Systemen. Verwende das dem System angemessene Zeilenende.

          Freundliche Grüße

          Vinzenz

          1. Hallo Vinzenz,

            Ich wuerde CRLF nehmen, also \r\n, das funktioniert auf allen Systemen.

            das ist falsch. Bitte lies den Artikel Plattformübergreifendes Handling von Zeilenumbrüchen.

            Mach ich gleich.

            Wenn Du auf einer Unix-Maschine ein Perlskript mit Windowszeilenenden (sprich CRLF = Carriage Return, Linefeed oder Wagenrücklauf und Zeilenvorschub) verwendest, so gibt es Fehler. Es funktioniert nach meiner Erfahrung also _nicht auf allen_ Systemen. Verwende das dem System angemessene Zeilenende.

            Das wusste ich nicht, ich dachte immer, wenn unter Unix nur das LF benutzt wird, wird das CR ja nicht stoeren und beim Mac genauso.

            Viele Grüße aus Freiburg,
            Marian

            --
            Microsoft broke Volkswagen's world record: Volkswagen only made 22 million bugs!
            <!--[if IE]><meta http-equiv="refresh" content="0; URL=http://www.getfirefox.com"><[endif]-->
        2. so nun funkt des...

          jetzt die frage:

          wenn eine liste von ips untereinander in einer txt datei ist,

          wie kann ich die alle auf einmal abfragen?

          also ich sollte ja die neue ip mit denen davor vergleichen, und dann danach, wie groß der zeitliche abstand ist.

          nur wie?

          welche funktion?

          ich kann ja nicht hundert mal if eingeben?

          1. Hallo newbie,

            wenn eine liste von ips untereinander in einer txt datei ist, wie kann ich die alle auf einmal abfragen?

            Wie gesagt, du suchst das letzte Vorkommen der IP. Ich wuerde zum Beispiel mit strrchr() den Text vor der IP wegschnibbeln und dann mit strchr() den nach dem Zeilenumbruch (welchen auch immer du nimmst, Hauptsache es ist der gleiche wie vorher).

            also ich sollte ja die neue ip mit denen davor vergleichen, und dann danach, wie groß der zeitliche abstand ist.

            Dann kannst du z.B. den String von oben mit explode() in drei Teile teilen, um den Zeitunterschied auszurechnen.

            Viele Grüße aus Freiburg,
            Marian

            --
            Microsoft broke Volkswagen's world record: Volkswagen only made 22 million bugs!
            <!--[if IE]><meta http-equiv="refresh" content="0; URL=http://www.getfirefox.com"><[endif]-->
        3. Hi,

          Die Zahl ist der UNIX-Timestamp, die Anzahl der Sekunden seit dem 1.1.1970. Den kriegst du einfach mit time(), und hinterher kannst du einfach gucken, ob der jetzige Timestamp minus der alte groesser als 24*60*60 ist.

          wieso dieser - zudem rechenaufwendige - Umweg?
          Du hast Sekunden und kannst direkt damit rechnen; welche Uhrzeit/Datum das ist, ist irrelevant, da nur die Differenz zählt.

          Ich würde folgendermaßen an di Sache herangehen:

          Speicherformat csv:
          Timestamp│Aufrufe│IP│Browserkennung

          • Datei in ein Array einlesen
          • Array sortieren (deshalb der Timestamp zuerst)
          • Einträge < aktueller Timestamp - 1800 nicht mehr berücksichtigen
          • Browserkennung und IP vergleichen
          • wenn dieselbe IP oder dieselbe Browserkennung und eine mehr oder weniger ähnliche IP (bei AOL z.B. den letzten Block nicht berücksichtigen) Zähler erhöhen, sonst Neueintrag
          • Datei sperren, neuschreiben und entsperren

          freundliche Grüße
          Ingo

          1. Hallo Ingo,

            ich stimme Dir weitgehend zu, aber (wie Tom gerne zu Recht ausgeführt hat) mit kleinen Ablaufänderungen:

            Ich würde folgendermaßen an di Sache herangehen:

            Speicherformat csv:
            Timestamp│Aufrufe│IP│Browserkennung

            • Datei sperren
            • Datei in ein Array einlesen
            • Array sortieren (deshalb der Timestamp zuerst)
            • Einträge < aktueller Timestamp - 1800 nicht mehr berücksichtigen
            • Browserkennung und IP vergleichen
            • wenn dieselbe IP oder dieselbe Browserkennung und eine mehr oder weniger ähnliche IP (bei AOL z.B. den letzten Block nicht berücksichtigen) Zähler erhöhen, sonst Neueintrag
            • Datei sperren, neuschreiben und entsperren
            • Datei neuschreiben und entsperren

            Warum? Tom hat es gerne ausführlich erklärt. Ich zeige den möglichen Fehler in Deinem Szenario auf:

            Anforderung von Client A
            Datei wird eingelesen, Array wird sortiert (das kann dauern :-))
            Anforderung von Client B
            Datei wird eingelesen (gleicher Stand), Array wird sortiert (das kann dauern :-))
            Datei wird gesperrt
            Änderungen von Client A werden weggeschrieben
            Datei wird entsperrt
            Datei wird gesperrt
            Änderungen von Client B an Originaldatei [sic!] werden weggeschrieben
            Datei wird entsperrt

            Änderungen von Client A sind weg.
            Daher _vor_ dem Lesen die Datei sperren.

            Freundliche Grüße

            Vinzenz

            1. Hi,

              ich stimme Dir weitgehend zu, aber (wie Tom gerne zu Recht ausgeführt hat) mit kleinen Ablaufänderungen:

              • Datei [zuerst] sperren

              Du hast natürlich recht, dass eine spätere Sperrung zu Fehlern führt, allerdings wäge ich die Wichtigkeit völlig korrekter Ergebnisse (die es hierbei ja ohnehin nicht geben kann) gegen die bei hoher Frequentierung unschönen Wartezeiten ab - bei niedriger Frequentierung wäre ein gleichzeitiger Zugriff eher selten un die Fehlerquote gering.

              Konkret könnte das bei Sperrung zu diesem Zeitpunkt bei heftiger Frequentierung dann nämlich so aussehen:

              Anforderung von Client A
              Datei wird eingelesen, Array wird sortiert (das kann dauern :-))
              Anforderung von Client B

              Datei kann nicht eingelesen werden - entweder Abbruch und Nichtzählung oder neue Versuche nach Wartezeit (das kann dauern...)

              Anforderung von Client C - der muß auch warten
              Client A ist fertig und hebt die Sperrung auf.
              Anforderung von Client D - der hat gerade Glück und darf die soeben freigegebehne Datei öffnen.
              Client B und C müssen immer noch warten.
              Anforderung von Client E
              ...
              Client B bekommt einen Timeout oder das Script gibt den Eintragsversuch auf.
              Client C bekommt ...

              Fazit: gerade bei einer solchen Aufgabe, deren Ergebnisse nun wirklich nicht exakt sind und auch nicht sein müssen, die aber bei jedem einzelnen Zugriff auf eine Seite bearbeitet werden muß, sollten die Besucher nicht unnötig darunter leiden.

              Und exaktere Auswertungen lassen sich hinterher über die Auswertung der Logfiles ohnehin noch machen.

              freundliche Grüße
              Ingo

  2. Hallo

    ich möchte einen besucherzähler haben, der die ip des besuchers in eine textdatei untereinander schreibt.

    Du hast Dir eine schöne, aber auch sehr aufwendige Aufgabe ausgesucht, um Dich mit PHP und seinen Möglichkeiten vertraut zu machen.

    127.0.0.1

    Wie Du hier im Forum (und seinem Archiv) oft genug lesen kannst, ist die IP-Adresse nicht unbedingt die beste Methode, einen Besucher zu erkennen. Zum einen gibt es Besucher, deren IP-Adresse sich während ihres Besuchs ändern kann, z.B. AOL-Kunden, deren Seitenabrufe mal über den einen mal über einen anderen AOL-Proxy abgewickelt werden können. Zum anderen gibt es verschiedene Benutzer, die die gleiche IP-Adresse aufweisen, z.B. verschiedene Firmenmitarbeiter, die sich einen Internetzugang (z.B. über einen Proxy oder einen Router) teilen.

    das wars zum ersten.
    das zweite:

    nun soll php die ips vergleichen und die doppelten ips löschen und dabei aber die ip einmal bestehen lassen und dahinter die anzahl der aufrufe schreiben.

    Nun ja, der zweite Punkt ist eigentlich der:
    Welche Seitenaufrufe zählst Du als einen Besuch. Soweit ich mich erinnere, wurde hier im Forum geäußert, dass ein Besucher eine halbe Stunde wegbleiben muss, bevor es ein erneuter Besuch ist. Stell' Dir vor, der Benutzer drückt auf die Reloadtaste seines Browsers. Dann darfst Du das im Normalfall nicht erneut zählen.

    Du siehst, einen Besucher _und_ einen Besuch zu identifizieren, ist gar nicht so einfach. Nun kommen wir zum Speichern in der Datei. PHP bietet eine Menge Funktionen zum Umgang mit Dateien, die meisten findest Du im Abschnitt Funktionen des Dateisystems des PHP-Handbuchs.

    127.0.0.1
    169.254.56.168
    127.0.0.1

    -->
    127.0.0.1 2
    169.254.56.168

    Wenn Du das so machen willst, dann hast Du z.B. folgende Möglichkeit:

    Bei Deinem Format musst Du mindestens ab der Zeile, in der die Änderung erfolgt, die Datei neu schreiben - ja, obwohl sich hinterher nichts geändert hat. In vielen Fällen gehen PHP-Programmierer (der Bequemlichkeit halber) sogar hin, und lesen die komplette Datei mit file() in ein Array aus, ändern den entsprechenden Arrayeintrag und schreiben die Datei mit file_put_contents() wieder weg.

    Beachte, dass zur gleichen Zeit, während die Datei in Bearbeitung ist, ein anderer Zugriff auf Deine Webseite erfolgen kann, die Du ebenfalls wegschreiben willst. Damit es nicht zu Problemen kommt, musst Du Sperren für die Datei setzen. Tom hat dies hier im Forum oft genug gepostet, z.B. in </archiv/2005/1/t99170/#m605523>.

    so und das dritte:

    php soll nun 2 ergebnisse präsentieren:

    einmal die anzahl der insgesamten aufrufe 8inkl. alles doppelten aufrufe der selben ip)

    Lese die Datei in ein (Zeilen-) Array ein. Durchlaufe das Array, trenne die Einträge in IP und Anzahl (wenn es eine Anzahl gibt), summiere Anzahl auf, gibt es in einer Zeile keine Anzahl so zähle 1 hinzu.

    und einmal nur die aufrufe von verschiedenen ips...

    Das ist doch die Ausgabe der kompletten Datei. Willst Du das wirklich?

    Ach ja, und wenn Dir noch ein paar Anforderungen ähnlicher Art einfallen, dann sieht es fast danach aus, als möchtest Du eine Datenbank benutzen.

    Freundliche Grüße

    Vinzenz