Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Resetuje mi sie licznik odwiedzin
Forum PHP.pl > Forum > PHP
yavaho
Co pewien czas (przypadkowo kiedy) resetuje mi sie licznik odwiedzin na dwoch roznych stronach, ktore maja taki sam kod php licznika. Nie wiem dlaczego? Spawdzalem nawet w kodzie we wszystkich plikach php i nigdzie nie znalazłem drugiej takiej samej zmiennej $licz_odw i $licz.
Strony mają ponad 1000 odwiedzin na dzien. Czy jest mozliwe ze 2 uzytkownikow na raz odczytuje plik "licznik.txt" albo moze jeden z nich nie moze odczytac w danym momencie tego pliku jak inny z niego korzysta i wtedy ten pierwszy podczas zapisu ustawia zerową wartość?
Moze ten kod licznika mam jakiś pokrecony?

  1. <?php
  2.  
  3. if(!isset($_SESSION['licz_odw'])){
  4. $file=fopen(&#092;"licznik/licznik.txt\", \"r\");
  5. flock($file, 1);
  6. $licz=fgets($file, 100);
  7. flock($file, 3); 
  8. fclose($file);
  9. $licz=$licz+1;
  10. $file=fopen(&#092;"licznik/licznik.txt\", \"w\");
  11. flock($file, 2);
  12. fwrite($file, $licz);
  13. flock($file, 3);
  14. fclose($file);
  15. $_SESSION['licz_odw'] = $licz;
  16. }
  17.  
  18. //tutaj zawartosc strony
  19.  
  20. echo('<p>'.$_SESSION['licz_odw'].'</p>');
  21.  
  22. ?>
Kuziu
Też kiedyś miałem podobny problem.
Rozwiązałem go może nie w najlepszy sposób ... bo nie mogłem znaleźć przyczyny ...

Zrobiłem to tak ... Po odczycie ... jeśli ilosc > 0 tworzyłem backup tego pliku ... a w wypadku gdy było =< 0 ... czyli licznik się zresetował ... kopiowałem plik z backup'u i nadpisywałem nim licznik.
KESS
To często spotykany problem. Najlepszym rozwiązaniem jest rezygnacja z pliku txt na rzecz bazt danych. Kasowanie licznika moze nastapic np. gdy ktos probuje pobrac Twoja strone programem typu Teleport, wtedy dane pobierane sa z badzo duza czestotliwoscia...
Kiedys mialem takze taka sytuacje, ze admin serwera grzebal cos z uprawnieniami do plikow i wszystkie liczniki poszly sie pasc :-(
dbk
Zrezygnowanie z licznika bazującego na plikach txt nie jest rozwiązaniem

Problem polega na odpowiednim skolejkowaniu dostępu/zapisu do plików - i na pewno będzie wydajniejszy od odwoływania się do bazy danych.

Tak na szybko - bo niestety nie mam czasu:
http://pl.php.net/manual/pl/function.flock.php
proponuję zajrzeć tutaj i podejrzeć rozwiązanie z 29-Sep-2004 01:04.

Trzeba pamiętać również o problemie nie pobrania pustej zawartości licznik.txt kiedy jest otwarty do zapisu - jak otwieramy z atrybutem 'w' to zawartość jest zerowana i wtedy może się licznik wysypać.
Wystarczy np pętelka while.
yavaho
Cytat(dbk @ 2005-02-24 11:15:08)
Trzeba pamiętać również o problemie nie pobrania pustej zawartości licznik.txt kiedy jest otwarty do zapisu - jak otwieramy z atrybutem 'w' to zawartość jest zerowana
Ale kiedy plik jest otwarty do zapisu to rownoczesnie zostaje zablokowany.
Chyba mam odpowiednio ulozone kolejkowanie dostepu do pliku?
Kocurro
1) otwierasz plik odczyt/zapis jednocześnie go blokując przed odczytem i zapisem
2) pobierasz licznik, zwiększasz, zapisujesz
3) zamykasz plik i odblokowujesz

dodatkowo po odczycie sprawdzasz czy np. lciznik nie jest mniejszy niz przykłądowo 10, 100 (jeśli wiesz, że już to przekroczył) i jeśli jest to nie robisz nic bo to oznacza bład w odczycie.
dbk
ten post to już w ramach jakiegoś offtopicu :] - bo już napisałem raz prawie to samo

przykładowa wersja jaka moze sie zdarzyc powodujaca przeklamania w pliku (a nawet go zerujaca)

- (1) proces pierwszy, (2) proces drugi.
- prawdopodobne wyarzenia w kolejności chronologicznej

1 otwiera, blokuje, zwieksza licznik, odblokuje, zamyka
2 otwiera, blokuje, zwieksza licznik, odblokuje, zamyka - ma zapisany ten sam stan licznika co 1
1 zapisuje swoje (z blokowaniem itd)
2 zapisuje swoje

wszystko łądnie pięknie z blokowaniem pliku - ale dane się nie zgadzają - a jeśli jeszcze akurat serwer wpadnie w jakaś zadumę to 2 odczyta pustke dla fopen 'w' i klapa.

sam tego nie wymyśliłem - wszystko w manualu php.net dla flock
Kocurro
dlatego stosuje się np. semafory ... lub bloki zapis/odczyt

poza tym głupota to dla licznika robić najpierw fopen 'r' a potem fopen 'w'...

to się robie jednym fopenem - odczyt danych, inkremetnacja, zapis...a atrybut trzeba dobrać - otworzenie z prawem do odczytu i zapsiu + blokada odczyt i zapis....

i wszystko działa - nawet przy tysiacu odświeżeń na minute licnzik taki mi się nie wysypał
yavaho
Przerobilem ten licznik, tylko czy teraz dobrze mam ustawiona blokade na odczyt i zapis?
  1. <?php
  2.  
  3. if(!isset($_SESSION['licz_odw'])){
  4. $nazwa = &#092;"system/licznik/licznik.txt\";
  5. $licz='';
  6. if($plik=fopen($nazwa, 'r+b')){
  7. flock($plik, LOCK_EX);
  8. $licz = fgets($plik);
  9. $licz++;
  10. fseek($plik, 0, SEEK_SET);
  11. fputs($plik, $licz);
  12. flock($plik, LOCK_UN);
  13. fclose($plik);
  14. }
  15.   $_SESSION['licz_odw'] = $licz;
  16. }
  17.  
  18. //tutaj zawartosc strony
  19.  
  20. echo('<p>'.$_SESSION['licz_odw'].'</p>');
  21.  
  22. ?>
Zrobilem tez wersje z drugim plikiem (backupem tego wlasciwego) ale jak na prosty licznik to juz bylo za duzo kodu smile.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.