Puffer in Schleife
Andreas
- programmiertechnik
0 Sönke Tesch0 Andreas0 Andreas0 Sönke Tesch0 Andreas
0 Calocybe0 Sönke Tesch0 Calocybe0 Andreas
Hallo!
Ich überlege gerade, wie ich in einer Tabelle die Verweildauer eines Users auf bestimmten Seiten anzeigen kann.
Und zwar trage ich auf jeder Seite(mit PHP) die SessionID den Dateinamen in eine Tabelle(mysql) ein. In der Tabelle wird außerdem ein Timestamp und eine ID beigefügt.
Jetzt frage ich per SELECT ab, WHERE SessionID='$sessionID'.
Jetzt habe ich einen Array mit allen Datensätzen einer "Session".
while($row=mysql_fetch_array($res)){
//Datensatz Timestamp:
$Sekunden=$row[changed]-$last_timestamp;
//Timestamp für nächchsten Datesatz speichern
$last_timestamp=$row[changed];
}
Das ist etwa so die Richtung, in die ich bis jetzt überlegt hatte, aber so geht es nicht, da beim ersten und letzten Datensatz nicht klarkomme, außerdem habe ich die Zeitdifferenz immer zu spät, erst beim nächsten Datensatz.
Ich müßte also so eine Art Puffer haben, also erst immer die daten in den Puffer laden, dann beim nächsten Datensatz den letzten Timestamp aus dem Puffer laden.
Nur wie macht man sowas?
Ich hab hier mal was von Puffern gelesen, aber nur in der Theorie, wie das genau praktisch gemacht wird, weiß ich nicht.
Kann mir jemand helfen?
Grüße
Andreas
Ich überlege gerade, wie ich in einer Tabelle die Verweildauer eines Users auf bestimmten Seiten anzeigen kann.
Und zwar trage ich auf jeder Seite(mit PHP) die SessionID den Dateinamen in eine Tabelle(mysql) ein. In der Tabelle wird außerdem ein Timestamp und eine ID beigefügt.
while($row=mysql_fetch_array($res)){
//Datensatz Timestamp:
$Sekunden=$row[changed]-$last_timestamp;
//Timestamp für nächchsten Datesatz speichern
$last_timestamp=$row[changed];
}
Das ist etwa so die Richtung, in die ich bis jetzt überlegt hatte, aber so geht es nicht, da beim ersten und letzten Datensatz nicht klarkomme, außerdem habe ich die Zeitdifferenz immer zu spät, erst beim nächsten Datensatz.
Die Verweildauer auf der letzten Seite wirst Du nie herausfinden können, weil Du für jede Seite nur einen "Anfang" hast, aber kein "Ende". Als Ende nimmst Du lediglich den Anfang der nächsten Seite an, diese nächste Seite liegt aber auf einem anderen Server (oder hinter dem Aus-Schalter des Computers) und darauf hast Du keinen Zugriff.
Du hast nicht geschrieben, für was Du die Zeiten brauchst, ich nehme deshalb mal eine einfache Ausgabe an. Die Schleife muß dafür etwas erweitert werden:
$row=mysql_fetch_array($res); // erste Seite holen
echo "<li>". $row["url"]; // und Adresse ausgeben
$last_timestamp=$row[changed];
while($row=mysql_fetch_array($res))
{
$Sekunden=$row[changed]-$last_timestamp;
echo $Sekunden;
echo "<li>". $row["url"];
$last_timestamp=$row[changed];
};
Ich hoffe, da ist morgens um zwei kein Denkfehler drin ;)
soenk.e
PS: Nicht jedes Seitenangucken erzeugt einen Eintrag auf dem Server, insofern ist Deine Statistik wahrscheinlich ungenau, meiner Erfahrung nach um bis zu 10%.
Hi!
Die Verweildauer auf der letzten Seite wirst Du nie herausfinden können, weil Du für jede Seite nur einen "Anfang" hast, aber kein "Ende". Als Ende nimmst Du lediglich den Anfang der nächsten Seite an, diese nächste Seite liegt aber auf einem anderen Server (oder hinter dem Aus-Schalter des Computers) und darauf hast Du keinen Zugriff.
Ja, das ist auch klar, aber die übrigen! Wenn ich damit irgendwann evtl mal was rechnen wirll nehme ich einfach den durchschnittswert der vorherigen Seiten oder sowas, aber das ist nicht so wichtig.
Du hast nicht geschrieben, für was Du die Zeiten brauchst, ich nehme deshalb mal eine einfache Ausgabe an. Die Schleife muß dafür etwas erweitert werden:
Was soll ich für Zeiten brauchen? Ich dachte an die Anzeige in Sekunden, was ja mit dem MySQL Timestamp nicht ohne weiteres auszurechnen ist, aber das hat ja nix mit dem problem zu tun, dafür habe ich mir schon ne Funktion geschrieben, die daraus einen Unix-Timestamp macht, die kann ich dann einfach subtrahieren.
$row=mysql_fetch_array($res); // erste Seite holen
echo "<li>". $row["url"]; // und Adresse ausgeben
$last_timestamp=$row[changed];
while($row=mysql_fetch_array($res))
{
$Sekunden=$row[changed]-$last_timestamp;
echo $Sekunden;
echo "<li>". $row["url"];
$last_timestamp=$row[changed];
};
Ach so, du machst den Umbruch einfach in der Schleife :-) Dummerweise dachte ich an eine Tabelle, da noch mehr Daten ausgelesen werden.
Wenn ich das mal umdenke - obwohl ich kann ja auch ein </tr><tr> statt <li> einfügen. Klar!
Vielen Dank, das sollte so funktionieren!
Grüße
Andreas
PS: Nicht jedes Seitenangucken erzeugt einen Eintrag auf dem Server, insofern ist Deine Statistik wahrscheinlich ungenau, meiner Erfahrung nach um bis zu 10%.
Ich mache das mit einem INSERT ganz am Anfang des Scriptes, wenn der User die Seite angezeigt bekommt, sollte es schon längst in der DB stehen. Wäre mir neu das nur 90% meiner INSERTs eingetragen würden?! Wie kommst Du da drauf?
Oder doch nicht?
$row=mysql_fetch_array($res); // erste Seite holen
echo "<li>". $row["url"]; // und Adresse ausgeben
$last_timestamp=$row[changed];
while($row=mysql_fetch_array($res))
{
$Sekunden=$row[changed]-$last_timestamp;
echo $Sekunden;
echo "<li>". $row["url"];
$last_timestamp=$row[changed];
};
Wenn ich das so mache, habe ich doch dieselbe URL stehen, wie im ersten Duchlauf durch die Schleife, oder? Der Unterschied ist nur, das in der ersten Zeile 0 Sekunden stehen wird, und in der 2. Zeile erst di richtige Zeit, oder?
Wie kann ich dafür sorgen, dass die Schleife erst beim 2. Element des Array anfängt?
Grüße
Andreas
$row=mysql_fetch_array($res); // erste Seite holen
echo "<li>". $row["url"]; // und Adresse ausgeben
$last_timestamp=$row[changed];
»»
while($row=mysql_fetch_array($res))
{
$Sekunden=$row[changed]-$last_timestamp;
echo $Sekunden;
echo "<li>". $row["url"];
$last_timestamp=$row[changed];
};
Wenn ich das so mache, habe ich doch dieselbe URL stehen, wie im ersten Duchlauf durch die Schleife, oder? Der Unterschied ist nur, das in der ersten Zeile 0 Sekunden stehen wird, und in der 2. Zeile erst di richtige Zeit, oder?
Nein, schau Dir das nochmal genau an:
In dem Teil vor dem while werden die Daten für die erste Seite geholt, dann die Adresse der ersten Seite ausgegeben und dann die Zeit in $last_timestamp gespeichert (aber noch keine Zeit ausgegeben).
In (!) dem while() werden bereits die Daten der nächsten Seite geholt. Dann (jetzt erste Zeile in der Schleife) wird der Abstand zwischen $last_timestamp (der Zeit der ersten Seite) und der aktuellen (also jetzt zweiten) Seite berechnet und ausgegeben. Die Ausgabe erfolgt aber noch hinter der Adresse der ersten Seite. Das ist die Verweildauer auf der ersten Seite, vom Abruf der ersten Seite bis zum Abruf der zweiten.
Erst dann wird ein neuer Listenpunkt (<li>) und mit ihm die Adresse der zweiten Seite ausgegeben. Nach dem Sichern der Abrufzeit der zweiten Seite geht die Schleife dann wieder von vorne los: Jetzt werden die Daten der dritten Seite geholt, der Abstand zwischen (in $last_timestamp gesicherter) Zeit der zweiten und der aktuellen dritten Seite ausgegeben usw.
Was übrigens die Sache mit "MySQL-Zeit nicht zur Berechnung von Sekundenabständen geeignet" angeht: MySQL hat eine Funktion namens unix_timestamp() eingebaut. Schau mal in die Anleitung, Abteilung "Functions for use in select and group by clauses".
Gruß,
soenk.e
$row=mysql_fetch_array($res); // erste Seite holen
echo "<li>". $row["url"]; // und Adresse ausgeben
$last_timestamp=$row[changed];
»»
while($row=mysql_fetch_array($res))
{
$Sekunden=$row[changed]-$last_timestamp;
echo $Sekunden;
echo "<li>". $row["url"];
$last_timestamp=$row[changed];
};
Hallo!
In dem Teil vor dem while werden die Daten für die erste Seite geholt, dann die Adresse der ersten Seite ausgegeben und dann die Zeit in $last_timestamp gespeichert (aber noch keine Zeit ausgegeben).
Aber das verstehe ich nicht. $row ist doch ein 2-Dimensionaler Array, in dem in der Ersten Dimension die Datensatze stehen und in der 2. jeweils die entsprechenden Elemente aus dem betroffenen Datensatz, oder? Also ist der Array doch "statisch", oder?
Am Anfang wählst Du dann automatisch den ersten Datensatz, unten in der Schleife fängt es doch wieder bei 0 an, da doch wieder neu auf den "Statischen" array zugegriffen wird, oder?
Den Rest verstehe ich schon.
Was übrigens die Sache mit "MySQL-Zeit nicht zur Berechnung von Sekundenabständen geeignet" angeht: MySQL hat eine Funktion namens unix_timestamp() eingebaut. Schau mal in die Anleitung, Abteilung "Functions for use in select and group by clauses".
Ja, das hatte ich auch gefunden, sehr praktische Sache :-) Aber gibt es sowas auch für die Ausgabe des "normalen" Datums, bzw. Uhrzeit aus dem MySQL Timestamp?
Viele Grüße
Andreas
Gruß,
soenk.e
In dem Teil vor dem while werden die Daten für die erste Seite geholt, dann die Adresse der ersten Seite ausgegeben und dann die Zeit in $last_timestamp gespeichert (aber noch keine Zeit ausgegeben).
Aber das verstehe ich nicht. $row ist doch ein 2-Dimensionaler Array, in dem in der Ersten Dimension die Datensatze stehen und in der 2. jeweils die entsprechenden Elemente aus dem betroffenen Datensatz, oder? Also ist der Array doch "statisch", oder?
Nein. $row ist (wie der Name eigentlich vermuten lassen sollte:) eine Zeile, d.h. ein Datensatz aus Deiner Datenbank-Tabelle. $row ist somit ein eindimensionales Feld.
Setze einfach mal oben in die Schleife ein
print_r($row);
ein und lass sie durchlaufen, dann siehst Du klarer, was sich da tut.
Am Anfang wählst Du dann automatisch den ersten Datensatz, unten in
Den ersten Datensatz ja, _nur_ den ersten. Der zweite Datensatz kommt dann mit dem zweiten mysql_fetch_xxx(). Pro Datensatz/Zeile erhälst Du eine Kombination URL/Abrufzeit.
Was übrigens die Sache mit "MySQL-Zeit nicht zur Berechnung von Sekundenabständen geeignet" angeht: MySQL hat eine Funktion namens unix_timestamp() eingebaut. Schau mal in die Anleitung, Abteilung "Functions for use in select and group by clauses".
Ja, das hatte ich auch gefunden, sehr praktische Sache :-) Aber gibt es sowas auch für die Ausgabe des "normalen" Datums, bzw. Uhrzeit aus dem MySQL Timestamp?
Schau mal in der Anleitung ein paar Absätze höher, da solltest Du über eine große Tabelle mit lauter %a, %b, %x stolpern, und darüber steht DATE_FORMAT().
Immer schön stöbern ;)
soenk.e
Moin moin!
PS: Nicht jedes Seitenangucken erzeugt einen Eintrag auf dem Server, insofern ist Deine Statistik wahrscheinlich ungenau, meiner Erfahrung nach um bis zu 10%.
Das wuerde mich mal interessieren. Wie gesichert ist diese Erfahrung? Wie gross ist die Datenbasis fuer diese Zahl? Wie erhaelt man die Fehlergroesse ueberhaupt?
So long
--
Rule of thumb -- every time Microsoft use the word "smart," be on the lookout for something dumb.
-- http://www.fourmilab.ch/webtools/demoroniser/
PS: Nicht jedes Seitenangucken erzeugt einen Eintrag auf dem Server, insofern ist Deine Statistik wahrscheinlich ungenau, meiner Erfahrung nach um bis zu 10%.
Das wuerde mich mal interessieren. Wie gesichert ist diese Erfahrung?
So sicher, wie alles im Netz ;)
Wie gross ist die Datenbasis fuer diese Zahl?
Zwischen 82.000 und 90.000 abgerufene Seiten monatlich, je nachdem, welche Zahl man nimmt :)
Wie erhaelt man die Fehlergroesse ueberhaupt?
Indem man auf jeder Seite eine kleine Grafik plaziert, die bei Abruf durch den Browser mitzählt. Wenn diese Zahl größer ist als die Zahl der Seitenabrufe aus der Statistik, deutet das darauf hin, daß die Seiten öfters angeschaut wurden als abgerufen.
Nun muß ich dazu sagen, daß ich auf meinem Server auch explizit Expires:-Kopfzeilen mitgeschickt habe und die Browser es somit etwas einfacher hatten, auf einen Abruf zu verzichten, als es wohl normalerweise der Fall ist.
Aber man kann es durchaus auch am eigenen Browser sehen, daß er zum Beispiel nicht jede Seite, die man durch "Zurück" erreicht, neu abruft.
Oder man wirft mal einen genauen Blick in das Serverprotokoll. Da finden sich (zumindest bei mir) öfters mal Stellen, an denen ein Browser die gleiche Seite mehrmals direkt hintereinander abgerufen hat, und zwar mit einer halben Minute Abstand oder mehr.
Das ist vielleicht kein Beweis, aber ein Indiz dafür, daß da zwischendurch noch was anderes angezeigt aber nicht abgerufen wurde. Denn wer drückt schon fünfmal auf den Reload-Knopp und braucht dafür auch noch drei Minuten?
Gruß,
soenk.e
Moin moin!
Indem man auf jeder Seite eine kleine Grafik plaziert, die bei Abruf durch den Browser mitzählt. Wenn diese Zahl größer ist als die Zahl der Seitenabrufe aus der Statistik, deutet das darauf hin, daß die Seiten öfters angeschaut wurden als abgerufen.
Ich nehme an, diese Grafik ist mit allen No-Cache-Direktiven bestueckt, die sich auftreiben liessen? ;-) Trotzdem ist leider nicht immer so sicher, vor allem wenn Proxies im Weg stehen, dass die Grafik bei jeder Seitenbetrachtung neu geladen wird, was bedeuten wuerde, dass die "reale" Abweichung noch groesser ist.
Nun muß ich dazu sagen, daß ich auf meinem Server auch explizit Expires:-Kopfzeilen mitgeschickt habe und die Browser es somit etwas einfacher hatten, auf einen Abruf zu verzichten, als es wohl normalerweise der Fall ist.
Das wiederum wuerde die "reale" Abweichung wieder kleiner machen, als die von Dir angegebene.
Aber man kann es durchaus auch am eigenen Browser sehen, daß er zum Beispiel nicht jede Seite, die man durch "Zurück" erreicht, neu abruft.
Kommt auch auf die Cache-Einstellungen an. Ich hab meinen Mozilla so eingestellt, dass er theoretisch bei jedem Seitenladen nochmal eine Rueckfrage machen muesste, ob die Seite sich geaendert hat (If-Modified-Since), es sei denn, fuer die Seite war von Anfang an ein Expires-Wert angegeben.
So long
--
Rule of thumb -- every time Microsoft use the word "smart," be on the lookout for something dumb.
-- http://www.fourmilab.ch/webtools/demoroniser/
(Ich muss langsam mal wieder nen neuen Spruch drunterhaengen *g*)
Hallo!
Vor allem könnt Ihr mir doch nicht wirklich weiß machen wollen, das wenn ich am Anfang jeder Seite, noch vor jedem html-Teil, per SQL-Abfrage ein INSERT ausführe und die Daten selbe logge!
Zwar wird nichts gemacht wenn man im Browser auf "zurück" klickt, aber dann solten doch auch kein Bilder nachgeladen werden, oder?
Grüße
Andreas
Vor allem könnt Ihr mir doch nicht wirklich weiß machen wollen, das wenn ich am Anfang jeder Seite, noch vor jedem html-Teil, per SQL-Abfrage ein INSERT ausführe und die Daten selbe logge!
Dein INSERT wird nur ausgeführt, wenn der Browser die Seite tatsächlich vom Server abruft. Wenn mein Browser die Seite aus seinem Cache holt, bekommst Du davon nichts mit, d.h. Dir "entgehen" ein paar Seite-angeguckt.
Zwar wird nichts gemacht wenn man im Browser auf "zurück" klickt, aber dann solten doch auch kein Bilder nachgeladen werden, oder?
Doch. Für jedes Objekt, das ein Server verschickt, gelten eigene Eigenschaften. Das ist bei Größe oder Dateiänderungszeit natürlich klar, gilt aber auch für Dinge wie das Verfallsdatum. Das bedeutet also das Verfallsdatum vom HTML-Dokument gilt nicht für die Grafiken, die dort verwendet werden.
Wenn nun explizit bei einem Objekt ein Verfallsdatum angegeben wird, das quasi schon abgelaufen ist, wenn das Objekt beim Browser ankommt, dann _muß_ er selbstverständlich dieses Objekt vor der nächsten Benutzung zumindest auf Änderungen prüfen - dafür ist so ein Verfallsdatum ja da.
Und diese Prüfung bedeutet grundsätzlich eine Anfrage an den Server; das gilt für HTML-Dateien genauso wie für Grafiken.
Von daher kann es durchaus sein, daß eine Zählgrafik deutlich öfter abgerufen wird als die Seite, auf der die Grafik steht.
Gruß,
soenk.e
Hi!
Das ist aber wirklich blöd, und vielleicht bin ja ja dann doch nicht so blöd(in anderer Hinsicht), denn ich habe mich auf den Kopf gestellt und manche Verläufe von Besuchen schlicht nicht verstanden!
Dagegen kann man ja evtl das Verfallsdatum in die Vergangenheit legen(bei mir der sicherste no-cache Mechanismus!), das sollte doch was bringen, oder? Bin mal gespannt ob sich dann an der Statistik was ändert!
Eine Frage noch - das mit dem Verfallsdatum mache ich ja mit dem HEADER in PHP. Wenn ich aber noch bevor der Header geschickt wird die Daten logge, also im PHP-Code vor dem no-cache Header stehen habe, bringt das auch nichts?
Grüße
Andreas
Hi Andreas,
Das ist aber wirklich blöd
ganz im Gegenteil. Es ist wunderbar. :-)
Stell Dir mal vor, Du hast eine HTML-Seite, welche Realtime-Informationen enthält. Diese Seite darf nicht gecached werden. Sie enthält aber eine Vielzahl von kleinen Markierungs-Bildchen, deren Inhalt sich "nie" ändert wird. Diese Bildchen dürfen sehr wohl gecached werden - gerne auch ein paar Tage oder Wochen.
(Nimm das Self-Forum als Beispiel, das erfüllt exakt die beschriebenen Forderungen.)
Und wenn der Server dem Browser schon bei der ersten Auslieferung mitteilt, wie lange der Inhalt dieser Bildchen sich ganz bestimmt nicht ändern wird, dann kann sich der Browser sparen, mit einem HTTP-Request von mindestens 500 Bytes plus genauso viel an Antwort überprüfen zu lassen, ob dir 50 Bytes Cache-Inhalt weiterhin verwendbar sind oder nicht.
Ich wüßte da eine Menge Einsatzfälle innerhalb des Self-Portals ... die fast 40% HTTP-304-Zugriffe der Webalizer-Statistik müßte sich bei geeigneter Konfiguration in den Bereich von 10% drücken lassen, denke ich. (Und das allein würde 1-2 GB Traffic pro Monat sparen, wie ich in einem anderen Posting hier mal hochgerechnet hatte.)
Dagegen kann man ja evtl das Verfallsdatum in die Vergangenheit legen
(bei mir der sicherste no-cache Mechanismus!), das sollte doch was
bringen, oder?
Je nachdem. "Expires:" ist HTTP/1.0 - es schadet nichts, für die HTTP/1.1-Clients auch ein "Cache-Control" mitzusenden, was diesen (ebenso wie auf dem Web befindlichen Proxy-Servern!) sehr viel genauer beschreiben kann, was sie tun sollen und was sie bleiben zu lassen haben).
Bin mal gespannt ob sich dann an der Statistik was ändert!
Ich mache gerade so etwas ... und bin gespannt auf die Statistik von morgen früh ...
Eine Frage noch - das mit dem Verfallsdatum mache ich ja mit dem
HEADER in PHP. Wenn ich aber noch bevor der Header geschickt wird
die Daten logge, also im PHP-Code vor dem no-cache Header stehen
habe, bringt das auch nichts?
Wenn der Browser keinen HTTP-Request abfeuert, dann wird Dein PHP-Skript überhaupt nicht aktiviert und kann auch nichts loggen.
Viele Grüße
Michael
Das ist aber wirklich blöd, und vielleicht bin ja ja dann doch nicht so blöd(in anderer Hinsicht), denn ich habe mich auf den Kopf gestellt und manche Verläufe von Besuchen schlicht nicht verstanden!
Da ham' wir den Salat :)
Dagegen kann man ja evtl das Verfallsdatum in die Vergangenheit legen(bei mir der sicherste no-cache Mechanismus!), das sollte doch was bringen, oder? Bin mal gespannt ob sich dann an der Statistik was ändert!
Mmh, also da möchte ich mal was zu denken geben:
Es ist wirklich nicht sinnvoll, den Browser zu zwingen jede Seite bei jedem Angucken neu zu laden. Der bzw. die Caches, die zwischen dem Browser und Deinem Server liegen, haben ja gerade die Aufgabe, sowas zu verhindern, da es Zeit und Systemresourcen verschwendet.
Mit dem ständigen Neuladen ärgerst Du im Endeffekt nur Deine Leser (Zeitverlust) und sämtliche beteiligten Netzbetreiber (unnötiger Datentransport=unnötige Kosten).
Dem gegenüber steht lediglich Deine Neugierde, den Lesern "nachzuspionieren".
Ich habe etwas ähnliches ja wie geschrieben auch mal gemacht (wenn auch en miniature mit einer winzigen 1x1x1-Grafik) und will und kann mich deshalb hier kaum als Netzheiliger aufspielen, aber meiner Erfahrung nach bringt es einfach nichts, wirklich jeden Zugriff im Protokoll zu haben.
Vielleicht haben ich bzw. mein Kino-Fahrplan andere Voraussetzungen als Du, ich kenne die Daten Deiner Seiten nicht, aber ich habe mich seinerzeit letztenendes nicht mehr für die Wege interessiert, die die Leser genommen haben, als vorher, geschweige denn irgendwelche überragenden Erkenntnisse daraus gewonnen. Und die angesprochenen bummelig 10% mehr oder weniger unterm Strich kratzen mich inzwischen auch nicht mehr.
So gesehen habe ich am Ende nur riesige Datenmengen angehäuft, die aber so gut wie nie besonders benutzt wurden.
Davon abgesehen: Wie ich ja nun inzwischen auch gelernt habe, ist man laut Datenschutzgesetz dazu verpflichtet, so wenig Daten wie möglich sammeln - und das ist auch gut so.
Gruß,
soenk.e