Licznik odwiedzin w PHP

wowo

Licznik w PHP

Ostatnio postanowiłem ulepszyć mój licznik tekstowy na stronie www o funkcję zliczania dziennego - tzw. licznik dzienny. Szukałem trochę w Internecie, znalazłem parę skryptów, ale niestety wszystkie posiadały jakieś niedoskonałości. Postanowiłem napisać taki licznik samodzielnie, oto jego kod źródłowy. Licznik wyświetla wszystkie odwiedziny strony oraz liczbę odwiedzin dzisiaj i wczoraj. Pierwsza część licznika - czyli ogólny licznik zliczający wszystkie odwiedziny to popularny skrypt, który lekko przerobilem. Druga część - licznik dzienny jest w całości moją pracą. Aby licznik działał dobrze należy umieścić na serwerze w folderze głównym pliki licznik.txt o zawartości 0; oraz dzienny.txt o zawartości np 2006-02-13:0:2006-02-12:0. Oba pliki muszą mieć prawa dostępu (CHMOD) 666. Licznik jest odporny na przeładowania strony, odwiedziny są zliczane raz na dobę.
Proszę o komentarze i oceny :) Jest to mój pierwszy artykuł na 4programmers.

<?php
function polnoc() /* odmierza ile sekund od danej chwili jest do konca dnia*/
{
    $teraz = date("H:i:s");
    $czas = explode(":", $teraz);
    $godziny = 23 - $czas[0];
    $minuty = 59 - $czas[1];
    $sekundy = 59 - $czas[2];
    $waznosc = $godziny * 3600 + $minuty * 60 + $sekundy;
    return $waznosc;
}

if ((!isset($_COOKIE['licznik'])) && (!strstr($_SERVER['HTTP_REFERER'], "www.nazwa-strony.pl"))) {
    $plik = fopen("licznik.txt", "r");
    $tekst = fread($plik, filesize("licznik.txt"));
    $dane = explode(";", $tekst);
    fclose($plik);
    $plik = fopen("licznik.txt", "w");
    flock($plik, 2);
    $dane[0]++;
    fwrite($plik, "$dane[0];", 15);
    flock($plik, 3);
    fclose($plik);

    /*LICZNIK DZIENNY - MADE BY WOWO */
    $data = date("Y-m-d"); /*zmienna przechowująca dzisiejszą datę*/
    $dzienny = fopen("dzienny.txt", "r"); /*otwieramy plik, plik jest formatu yyyy-mm-dd:liczba:yyyy-mm-dd:liczba, gdzie pierwsza data jest data dzisiejsza, pierwsza liczba liczbą odwiedzin dzisiaj, druga data, to data wczorajsza, druga liczba to liczba odwiedzin wczoraj*/
    $dzienny_tekst = fread($dzienny, filesize("dzienny.txt")); /*czytamy caly plik do zmiennej dzienny_tekst*/
    $dane2 = explode(":", $dzienny_tekst); /*rozbijamy wczytany tekst z pliku, na daty i liczby klikniec - calosc bedzie w tabeli*/
    fclose($dzienny); /*zamykamy plik, ktory otwarlismy tylko do odczytu*/

    if ($dane2[0] == $data) /*jesli w pierwsza data w pliku jest data dzisiejsza to dzialamy jak nizej*/ {
        $dane2[1]++; /*zwiekszamy liczbe klikniec dzisiaj*/
        $dzienny = fopen("dzienny.txt", "w"); /*otwieramy plik do zapisu*/
        flock($dzienny, 2); /* blokujemy plik przed zapisem*/
        fwrite($dzienny, "$dane2[0]:$dane2[1]:$dane2[2]:$dane2[3]", 30); /*zapisujemy calość do pliku */
        flock($dzienny, 3); /* odblokowujemy plik */
        fclose($dzienny);   /* zamykamy plik */
    } else/* jeśli pierwsza data w pliku nie jest dzisiejszą datą */ {
        $dane2[2] = $dane2[0]; /* druga date w pliku ustawiamy, ta ktora byla do tej pory pierwsza*/
        $dane2[3] = $dane2[1]; /* druga liczbe odwiedzin ustawiamy, ta ktora byla do tej pory pierwsza*/
        $dane2[0] = $data; /* ustawiamy pierwsza date w pliku na date dzisiejsza*/
        $dane2[1] = 1; /* liczbe klikniec ustawiamy na 1 bo sa to pierwsze odwiedziny tego dnia*/
        $dzienny = fopen("dzienny.txt", "w"); /*otwieramy plik do zapisu*/
        flock($dzienny, 2); /*blokada zapisu*/
        fwrite($dzienny, "$dane2[0]:$dane2[1]:$dane2[2]:$dane2[3]", 30); /*zapisujemy calość do pliku */
        flock($dzienny, 3);/* odblokowujemy plik */
        fclose($dzienny);/* zamykamy plik */
    }

    setcookie("licznik", "zliczono", time() + polnoc() + 1); /* cookie blokuje licznik do konca doby */
} else {
    $plik = fopen("licznik.txt", "r"); /* obsluga licznika stalego*/
    $tekst = fread($plik, filesize("licznik.txt"));
    $dane = explode(";", $tekst);
    fclose($plik);

    $dzienny = fopen("dzienny.txt", "r"); /* obsluga licznika dziennego*/
    $dzienny_tekst = fread($dzienny, filesize("dzienny.txt"));
    $dane2 = explode(":", $dzienny_tekst);
    fclose($dzienny);
}

Przykład użycia licznika:

Stronę odwiedziło:<?php echo($dane[0]); ?> gości.
Dzisiaj (<?php echo($dane2[0]); ?>) stronę odwiedziło: <?php echo($dane2[1]); ?> gości.
Wczoraj (<?php echo($dane2[2]); ?>) stronę odwiedziło: <?php echo($dane2[3]); ?> gości.

10 komentarzy

Witam, jestem w tym laik, czy ktoś może wyjaśnić mi krok po kroku aby to działało na stronie?? :)

Musicie buforowac dane wysciowe. Posłużcie sie ob_start(); i zakonczcie ob_end_flush();

Zauważyłem, że ze skryptem dzieje się coś dziwnego.
Wszystko było OK.
Zmieniłem jednak datę w swoim komputerze o 2 dni do przodu i ... licznik oszalał.
Przy każdym odświeżeniu doliczał wizytę oraz wizytę dzisiejszą.
Daty w pliku dzienym nie zmienił.
Teoretycznie można ząłożyć, że coś takiego zrobi inny użytkownim strony i dojdzie wówczas do solidnego przekłamania.
Co wy na to?

Taki błąd mi się pojawił i nie wiem gdzie jest błąd.
Warning: Cannot modify header information - headers already sent by (output started at /home/intelal/public_html/ple22/index.php:10) in /home/intelal/public_html/ple22/index.php on line 173

Taki błąd mi się pojawił i nie wiem gdzie jest błąd.
Warning: Cannot modify header information - headers already sent by (output started at >/home/intelal/public_html/ple22/index.php:10) in /home/intelal/public_html/ple22/index.php on line 173

Miałem to samo. Zakładając, że kod licznika masz w pliku licznik.php, to <?php include "licznik.php";?> musisz umieścić w pierwszej linii kodu strony. U mnie zadziałało. Dowód: www.nervovoohozy.roszcza.pl

@infal: za pomocą funkcji php chmod, lub przy użyciu jakiegoś menadżera plików ze strony www, ale z tego co piszesz to takiego chyba tam nie ma.

korzystam z www.za.pl i www.friko.pl (łącznie www.8.pl). Przesyła sie tam informacje za pomocą serwera ftp. W jaki sposób nadać plikowi prawa dostępu (ów atrybut CHMOD)??

@Coldpeer - już myślę o zliczaniu odwiedzin tygodniowych i miesięcznych :) Jak znajdę chwilę czasu to taką opcję dodam :-)

@SebaZ: albo FAQ :)
@wowo: A może dodasz jeszcze np. miesiąc, tydzień itp?

A swoją drogą, dzięki temu "artykułowi", naszła mnie myśl, żeby stworzyć sobie taki licznik na bazie (z uwzglednieniem dni, tygodni) :)

to raczej gotowiec niż artykuł