Mintapélda
Helyezzünk el a weboldalunkon egy számlálót, mely mutatja, hányan látogatták meg a mai napon
eddig az oldalunkat!
A legegyszerűbb megoldás alapgondolatát az jelentheti, ha
- az eddigi látogatók számát egy közönséges text fájlban tároljuk,
- minden új látogató esetén ezt a számot eggyel növeljük,
- az aktuális számértéket pedig a weblapon megjelenítjük.
Ennek megvalósításához fájlkezelés szükséges, aminek legfőbb műveletei
Szükségünk lesz még két kiegészítő függvényre a következő lehetőségekkel:
Ezekkel már könnyen teljesíthető a feladat:
<?
$fajlnev = date("y-m-d") . ".txt" ; // (1)
if( file_exists($fajlnev) ) // (2)
{
$f = fopen( $fajlnev , "r" ) ;
$n = fread( $f , filesize($fajlnev) ) ;
fclose( $f ) ;
}
else // (3)
{
$n = 0 ;
}
$n++ ; // (4)
$f = fopen( $fajlnev , "w" ) ; // (5)
fwrite( $f , $n ) ;
fclose( $f ) ;
print "Oldalletöltések száma: $n" ; // (6)
?>
A programban számmal jelzett részekkel az alábbi feladatokat végezzük el:
- (1)A számláló értékét tartalmazó fájl nevét a mai dátumból képezzük, kiterjesztése txt. Ezzel az elnevezéssel egyben azt is megoldjuk, hogy minden naphoz önálló fájl tartozzon, vagyis csakugyan napi számlálást fogunk végezni.
- (2)Ha már létezik ez a fájl, akkor olvasásra megnyitjuk, és $n változóba kiolvassuk belőle a tartalmát, majd bezárjuk a fájlt.
- (3)Ha a fájl még nem létezik, akkor is létrehozzuk $n változót, és értékét nullára állítjuk.
- (4)Eggyel megnöveljük $n változó értékét.
- (5)Létrehozzuk a számláló értékét tartalmazó fájlt (ha már létezett, akkor most felülírjuk), és $n értékét belementjük. A fájlt bezárjuk.
- (6)Képernyőn is megjelenítjük $n új értékét, vagyis a mai eddigi látogatók számát.
Oldalletöltések száma: 1521
Egy nem várt probléma
Azonban van egy komoly probléma ezzel a megvalósítással: a számláló jelenleg
nem a látogatókat,
hanem az oldalletöltéseket számolja. Ugyanis az oldal minden frissítése után eggyel
tovább növekszik a számláló, nem pedig csak az új látogatók esetén.
Kérdés tehát:
hogyan különböztessük meg az egyes látogatókat? IP címük alapján? Időkorlát
alapján? Ezek nem tökéletes megoldások, hiszen pl. egy iskolai teremben jó eséllyel minden gép
ugyanazon az IP-címen van (mert csak a belső hálózaton különböznek egymástól), pedig különböző
felhasználók ülnek a gépek előtt. Illetve attól, hogy egy adott látogató pl. majd csak egy óra
múlva frissíti az oldalt, attól még ő ugyanaz a látogató marad. De akkor mi jelentheti a
megoldást?
Általában egyazon felhasználó tevékenysége alatt azt a folyamatot értjük, ami a böngészője
megnyitásával kezdődik, és annak bezárásával végződik. Az e két esemény között eltelt időt
munkamenetnek, vagy szakmaibb kifejezéssel élve
session-nek hívjuk. Ha meg
tudnánk valósítani, hogy munkamenetenként csak egyszer számoljon a számláló, akkor készen
is lennénk a megoldással.
A munkamenet, vagyis a session használata
A fentiekben megfogalmazott cél eléréséhez a
PHP session-kezelő lehetőségeit
kell segítségül hívni. Ezen belül első lépésként szükségszerű egy munkamenetet indítanunk
a kiszolgáló webszerveren, hogy mint felhasználók, ott is azonosíthatóak legyünk. Ehhez a
session_start()
függvényt kell felhasználnunk, melynek eredményeként csakugyan kapunk a szervertől egy
úgynevezett session-azonosítót, ami csak a miénk, és csak az adott munkamenetre vonatkozik.
Bár a saját session-azonsítónkat lekérdezhetjük a
session_id
függvénnyel - jelenleg ez így néz ki:
58e8kcr203ctvceke4bp9c0iv5
hossza 22-40 karakter közötti, véletlenszerű betűkből és számokból áll -, ennek azonban
számunkra nagy gyakorlati jelentősége nincsen, hiszen ez csupán a szerveren fontos adat
a mi ottani azonosíthatóságunk céljából.
$_SESSION
Ám onnantól kezdve, hogy indítottunk egy munkamenetet, már használhatjuk a
$_SESSION
változót, és
ez lesz számunkra az igazán fontos. Ez a változó egy olyan speciális,
tömb típusú változó, melyben általunk megadott adatokat tudunk eltárolni úgy, hogy ezen
adatok nemcsak az aktuálisan futó PHP programunk ideje alatt maradnak elérhetőek, hanem
egészen addig, amíg a munkamenetünk létezik. Ebben az a legnagyszerűbb, hogy adatokat
tudunk továbbvinni egyik oldalról a másikra.
Mire lehet jó a $_SESSION ?
Két nagyon tipikus felhasználását érdemes megemlíteni:
1.
Regisztrációt követő bejelentkezést megvalósító oldalak esetén a
$_SESSION változóban tároljuk el a beléptetett felhasználó valamilyen
azonosítóját azért, hogy minden további oldalon megmaradjon a belépés
ténye, vagyis ne kelljen minden új oldal megnyitásakor újra és újra
bejelentkezni.
2.
Webáruházak esetén a $_SESSION változó szolgál a vásárlói kosár
adatainak eltárolására is. Ezáltal válik lehetővé, hogy a webshop
különböző oldalai között ugrálva-böngészve folyamatosan gyűjtögethessük
a megvásárolni kívánt termékeket a kosárban.
Tehát mitől lesz látogatottság-számláló?
Ennyi ismeret birtokában már sejthető, hogy a látogatóinkat is a $_SESSION tömb segítségével
fogjuk nyomon követni, vagyis ennek segítségével fogjuk megoldani, hogy minden látogató
csak egyszer (az áltata megnézett legelső oldal megtekintése alkalmával) növelje a számláló
értékét a böngészése során. De hogyan?
- A program elején elindítjuk a munkamenetet - vagy visszanyerjük belőle
az adatokat. (7)
- Amikor a felhasználó először letölt egy oldalt, akkor elhelyezünk
egy tetszőleges bejegyzést a $_SESSION változóban. (9)
- Mielőtt az oldalletöltéssel egyidejűleg növelnénk a korábbi mintapéldánkban
létrehozott számláló értékét, megvizsgáljuk, hogy létezik-e már a $_SESSION változóban az
általunk használni kívánt bejegyzés. (8)
- Ha nem létezik, akkor az nyilván azért van, mert épp az imént nézi
meg emberünk legelőször az oldalt - tehát növeljük a számláló értékét. (4)-(5)
- Ha már lézezik, akkor az azért van, mert korábban már megnézte
emberünk az oldalt - tehát nem növeljük a számláló értékét, vagyis nincs dolgunk.
Mindezeket beépítve a korábban megírt programunkba, az alábbi kódot kapjuk (benne színessel
kiemelve az újdonságokat):
<?
session_start(); // (7)
$fajlnev = date("y-m-d") . ".txt" ; // (1)
if( file_exists($fajlnev) ) // (2)
{
$f = fopen( $fajlnev , "r" ) ;
$n = fread( $f , filesize($fajlnev) ) ;
fclose( $f ) ;
}
else // (3)
{
$n = 0 ;
}
if( !isset( $_SESSION['valami']) ) // (8)
{
$n++ ; // (4)
$f = fopen( $fajlnev , "w" ) ; // (5)
fwrite( $f , $n ) ;
fclose( $f ) ;
$_SESSION['valami'] = 1 ; // (9)
}
print "Oldalletöltések száma: $n" ;
print "Mai látogatók száma: $n" ; // (6)
?>
Az ekképpen megvalósított programunk által működtetett számláló értéke már nem fog növekedni
az oldal frissítésének hatására:
Mai látogatók száma: 1493
Persze, ha közben bárhol máshol, más felhasználó is elkezdi nézni az oldalt, akkor azt már
a számláló 1 új látogatóként érzékeli, és számolja.
Kiegészítő gondolatok
A megvalósított számláló kapcsán terítékre került elméleti megfontolásokat érdemes
még néhány gondolattal kiegészíteni.
- A session_start() függvény hívását mindig a program elején
kell megtennünk - precízen fogalmazva akkor, amikor még semmilyen kiírást
nem követtünk el a weblapon.
- Bár fentebb úgy fogalmaztunk, hogy a munkamenet a böngésző bezárásával
ér véget - ez csak részben igaz. A munkamenet akkor is véget érhet, ha
"túl sokáig" nem kommunikálunk a szerverrel, vagyis pl. nem ülünk a gép
előtt. Ekkor ugyanis lejárhat a session-idő, ami azt jelenti, hogy
elveszítjük a $_SESSION változóban eltárolt értékeinket. A szerveren
beállított session-idő (másodpercben értelmezett) értékét a
phpinfo() függvénnyel tudjuk lekérdezni,
és a kapott képernyő session.gc_maxlifetime sorából kiolvasni.
- Ha privát böngészőt nyitunk, akkor az másik böngészőnek, és így
másik munkamenetnek számít. Ennek megfelelően ott mi magunk is új
látogatók leszünk ugyanazon az oldalon.
- Számlálónk a keresőrobotok látogatásait is látogatásként értelmezi,
vagyis ezek is növelik a mutatott értéket. Ennek kiküszöbölése ugyan
nem lehetetlen, de mindenképpen összetettebb látogatói adatelemzést
igényel.
Ábrázoljuk!
Készítsünk statisztikát, melyen az elmúlt hét látogatottságát mutatjuk be egyszerű grafikus
formában a fent képzett számaink alapján! Eredményül például az alábbi ábrát kaphatjuk:
Napi látogatottsági adatok
|
|
|
|
|
|
|
|
11.04 |
11.05 |
11.06 |
11.07 |
11.08 |
11.09 |
11.10 |
11.11 |
oldalletöltések száma
látogatók száma
Természetesen ahhoz, hogy a fenti diagram mintájára az oldalletöltések számát is,
és a látogatók számát is ábrázolni lehessen, korábban meg kellett oldani, hogy
mind a két adat eltárolásra kerüljön.
Kételkedjünk!
A kapott ábra alapján több napi adat helyességével kapcsolatban is kételyeink támadhatnak.
Ugyanis általában egy weboldal esetén a látogatók egy része csak egyetlen lapot tekint meg
(azt, ahova a keresőből érkezik), de vannak jó néhányan, akik viszont 2-3 lapot is megnéznek,
például mert a kezdőlapra érkeztek és onnan haladnak a mélyebb tartalom irányába, vagy mert
érdekes volt számukra az első olvasott lap, és még kattintanak párat a belső linkek mentén.
Ennek az a jellemző eredménye, hogy
a lapletöltések száma átlagosan nagyjából a kétszerese
szokott lenni a látogatók számának. Ám ha a grafikonunk ettől durván eltérő adatokat mutat,
ráadásul nem is következetesen, akkor
gyanakodhatunk, hogy valami nem jó.
De mi lehet a baj?
Felmerülhet például a gondolat, hogy vajon minden oldalletöltést, és minden látogatót számolunk-e.
Ebből akár arra is gyanakodhatunk, hogy esetleg néha, valami véletlen hiba folytán időnként nem
nullázódnak-e a számlálóink. A gyanú alapja, hogy olykor olyan napi adatokba is beleszaladhatunk,
amikor a látogatók száma nagyobb, mint az oldalletöltések száma - miközben ez nyilván lehetetlen.
Könnyen belátható, hogy
a megírt programunk kritikus pontja a fájl újraírása. Hiszen
ha egy új látogató számlálása céljából éppen akkor nyitjuk meg a számot tartalmazó szöveges
fájlt, amikor egy mindössze néhány század másodperccel korábban érkező látogató látogatásának
számlálása még nem fejeződött be, vagyis épp nem létezik az újraírni szándékozott fájl, akkor
az új látogató számlálása gyakorlatilag nullázza is az eddigi számlálást, merthogy
új fájlt fog
készíteni neki a programunk, felülírva ezzel a korábbi tartalmat.
Hogyan javíthatjuk ki?
Ha a felülírás a baj, akkor érdemes a felülírást megszüntetni. Ezt megtehetjük például úgy,
hogy egy-egy új látogató, illetve oldalletöltés esetén nem számlálóban rögzítjük az
aktuális számot (és azt mindig újraírjuk), hanem helyette egy erre a célra készített fájlban
"strigulázunk", vagyis mindig egy-egy új karakter bejegyzésével (hozzáfűzésével) növeljük
a fájlban lévő karakterek számát. A karakter "értéke" itt bármi lehet, ennek most semmi
jelentősége, ám a fájlban lévő karakterek száma, és ekképpen
a fájl hossza megadja
a látogatók, illetve a lapletöltések számát.
Győződjünk meg róla!
Az infojegyzet.hu ezen a javított módon is számolja az oldal napi látogatóit, illetve
az oldalletöltéseket, így össze tudjuk hasonlítani az első (hibás) módszer, és a
második (javított) módszer számait. Ezt láthatjuk az alábbi táblázatban.
Dátum |
oldalletöltés |
látogatószám |
arány |
hibás |
javított |
hibás |
javított |
hibás |
javított |
11.04 H |
8158 |
8160 |
1910 |
2412 |
4.27 |
3.38 |
11.05 K |
3226 |
5485 |
824 |
2226 |
3.92 |
2.46 |
11.06 Sz |
5281 |
5281 |
2215 |
2215 |
2.38 |
2.38 |
11.07 Cs |
1877 |
6883 |
394 |
2700 |
4.76 |
2.55 |
11.08 P |
5526 |
5528 |
2294 |
3647 |
2.41 |
1.52 |
11.09 Sz |
1101 |
1756 |
1439 |
1439 |
0.77 |
1.22 |
11.10 V |
4560 |
4561 |
2192 |
3193 |
2.08 |
1.43 |
11.11 H |
1520 |
3733 |
1493 |
2069 |
1.02 |
1.8 |
A táblázat eredményeit szemlélve teljesen egyértelművé válik, hogy míg az első közelítésből
megírt látogatottság-számláló programunk adatfájljai naponta akár többször is nullázódhatnak,
és ezáltal valójában teljesen megbízhatatlan értékeket produkálnak, addig a "strigulázós"
módszer jóval megbízhatóbbnak tekinthetően működik, és szépen "hozza" a
2 körüli oldalletöltés / látogató arányt.
Feladatok
1.
A fentiek értelmében írja át a saját oldalletöltés- és látogatottság-számláló programját úgy,
hogy az ahhoz tartozó adatfájlban ne számértéket tartson nyilván, hanem a benne szereplő
karakterek száma határozza meg a tárolni kívánt számértéket. Ehhez alapvetően két dolgot kell
megoldania:
- számoláskor az eddigi újraírás helyett egy új karakter hozzáfűzésével bővítse a fájlt;
- a fájl tartalmának kiolvasása helyett csupán a fájl hosszát kell meghatároznia.
2.
Tegye elegánsabbá a számláló kinézetét azzal, hogy nem szöveges kiírással jeleníti meg az
aktuális értéket, hanem valamilyen grafikus formában, például az alábbiak szerint:
Ehhez jó alapanyagot találhat a
oldalon, melyek közül a fenti képen az
Odometer Black számtípus látható.
Összegzés
Természetesen a javított programváltozatunk sem elegendő még egy minden jogos igényt kielégítő látogatottsági statisztika
vezetéséhez. E jelen lapnak nem is ez volt az elsődleges célja, hanem a fájl- és session-kezeléssel kapcsolatos alapvető
gondolatok bemutatása.
Az életszerű látogatói statisztikák alapját nem szöveges fájlok jelentik, hanem az adatbázisban tárolt lapletöltések
adatainak rekordjai. Ez utóbbiak ugyanis akár azt is lehetővé teszik, hogy közülük
kiszűrjük, és külön kezeljük a robotok látogatásait,
és a statisztikában minél inkább csak a valós felhasználók lapletöltéseit szerepeltessük. Ezen az elven
működik az
infojegyzet.hu API-ja is, mely az alábbi linken érhető el:
api.infojegyzet.hu/latogatottsag/
Erről az
API-ról a következő oldalakon is szó esik még: