Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

PHP - Licznik odwiedzin resetuje się

11111olo 05 Lut 2014 13:35 4917 33
  • #1 05 Lut 2014 13:35
    11111olo
    Poziom 43  

    Witam.
    Dodałem do strony licznik odwiedzin, który działa poprawnie, jednak przy większym ruchu resetuje się. Wiem, że problem tkwi podczas zapisu gdy jednocześnie plik jest otwarty. Nie potrafię rozwiązać tego problemu.

    Kod: php
    Zaloguj się, aby zobaczyć kod


    Nie chcę aby ktoś napisał gotowiec a jedynie o wskazówkę.

    0 29
  • #2 05 Lut 2014 14:08
    arnoldziq
    Moderator Programowanie

    Robisz kilka błędów.
    1. Po co wykonujesz jakiekolwiek operacje pomiędzy otwarciem pliku a jego zamknięciem? Otwarcie, odczyt czy zapis i zamknięcie. Każda operacja pomiędzy otwarciem i zamknięciem wymaga czasu, w którym inne wywołanie skryptu może sobie ten plik przywłaszczyć (albo chociaż próbować).
    2. Zastosuj taką strukturę:

    Kod: php
    Zaloguj się, aby zobaczyć kod
    Albo pętlę oczekiwania na uzyskanie dostępu exclusive do pliku.
    3. Nie bardzo rozumiem po co zapisujesz a potem odczytujesz i liczysz na piechotę ilość linii w pliku. Czytaj i zapisuj do kilku plików tylko samą cyfrę. Kilka bajtów i operacja właściwie "no time".

    0
  • #3 05 Lut 2014 14:32
    11111olo
    Poziom 43  

    1. Wcześniej nie było innych operacji pomiędzy otwarciem i zapisem i też nie działało prawidłowo, dlatego chciałem spróbować inaczej, jednak bezskutecznie.
    2. A co jeśli warunek nie zostanie spełniony? Zapis nie zostanie wykonany a nie oto przecież chodzi.
    3. Najpierw jest sprawdzane czy otwarta strona to strona główna, jeśli tak to jest pomijane wyświetlanie i zliczanie licznika odwiedzin.
    Gdy nie jest to strona główna to sprawdzane jest czy istnieje wpis do tej konkretnej strony na której obecnie się znajdujemy i gdy jest znaleziony zostaje wyświetlona ilość odwiedzin.
    Na koniec jest zapisywana ilość odwiedzin zwiększona o jeden.

    A liczenie ilości w pliki jest po to aby zapis nastąpił do odpowiedniej linii.
    Przykładowo wygląd pliku:

    12,strona1
    3,strona2
    122,strona3
    46,strona4
    63,strona5
    1,strona6

    0
  • #4 05 Lut 2014 14:40
    arnoldziq
    Moderator Programowanie

    11111olo napisał:
    A liczenie ilości w pliki jest po to aby zapis nastąpił do odpowiedniej linii.
    Przykładowo wygląd pliku:

    12,strona1
    3,strona2
    122,strona3
    46,strona4
    63,strona5
    1,strona6

    Nie, no ja to rozumiem. Tylko nie widzę celowości takiego zapisu.
    Zrób sobie osobny katalog na licznik i niech skrypt tworzy w nim pliki strona1.dat, strona2.dat itd. itp.
    A do tych plików zapisuj tylko cyferkę. Proste i wydajne.
    W twoim wykonaniu, odczytanie tych kilku linii, chop, podział, sprawdzenie, zwiększenie wartości i zapis całej struktury trwa po prostu zbyt długo. Stąd problemy z konkurencyjnymi procesami.

    Dodano po 1 [minuty]:

    A skoro pokazujesz liczbę odwiedzin tylko na jednej stronie, to po co liczysz ją dla każdej strony osobno?

    0
  • #5 05 Lut 2014 14:47
    11111olo
    Poziom 43  

    arnoldziq napisał:
    A skoro pokazujesz liczbę odwiedzin tylko na jednej stronie, to po co liczysz ją dla każdej strony osobno?


    Nie napisałem czegoś takiego.
    Dla każdej strony jest wykonywany ten sam skrypt, tylko na stronie głównej - index, jest to pomijane.

    0
  • #6 05 Lut 2014 14:49
    arnoldziq
    Moderator Programowanie

    No to OK.
    1. Osobny katalog.
    2. Osobne pliki dla każdej strony, w zależności od jej nazwy.
    3. Zapis tylko cyferki dla każdego pliku.
    4. Pętla oczekująca na przyznanie dostępu exclusive do danego pliku.

    0
  • #7 05 Lut 2014 15:31
    11111olo
    Poziom 43  

    Troszkę się zagalopowałem pisząc 2 post w tym temacie.

    12,/strona1
    3,/strona2
    122,/strona3
    46,/strona4
    63,/strona5
    1,/strona6

    Jednak niektóre wiersze wyglądają tak:
    12./folder1/strona1
    3,/folder1/strona2
    122,/folder1/strona3
    46,/folder1/strona4
    63,/folder1/strona5
    1,/folder1/strona6

    i teraz jak rozwiązać problem z nazwami plików?
    Pozbycie się / spowoduje dziwne nazwy jak np. folder1strona1.

    BTW. Czemu tu odpowiedź jest za 0 pkt. (Odpowiedź (0 pkt)) ale jak klikniesz odpowiedz to pomiędzy nowy temat i rozwiązano to wtedy odpowiedź jest za 1 pkt. (Wyślij (1 pkt))?

    0
  • #8 05 Lut 2014 15:39
    arnoldziq
    Moderator Programowanie

    11111olo napisał:
    Pozbycie się / spowoduje dziwne nazwy jak np. folder1strona1.

    Zamieniaj '/' na '_' i sprawa załatwiona.
    Zasada pozostaje ta sama.
    11111olo napisał:
    BTW. Czemu tu odpowiedź jest za 0 pkt. (Odpowiedź (0 pkt)) ale jak klikniesz odpowiedz to pomiędzy nowy temat i rozwiązano to wtedy odpowiedź jest za 1 pkt. (Wyślij (1 pkt))?

    W tym dziale każda odpowiedź jest punktowana jednym punktem. Ale jak odpowiadasz we własnym temacie, to chyba nie oczekujesz za to punktów? :P

    0
  • #9 05 Lut 2014 15:44
    11111olo
    Poziom 43  

    Tylko wtedy każda nazwa pliku będzie od _.
    Wszystko wydaje mi się zrozumiałe, napiszę kod i umieszczę.

    0
  • #10 05 Lut 2014 15:46
    arnoldziq
    Moderator Programowanie

    11111olo napisał:
    Tylko wtedy każda nazwa pliku będzie od _.

    A w czym to przeszkadza?

    0
  • #11 05 Lut 2014 17:37
    Dżyszla
    Poziom 42  

    Ja tylko króciutko się wtrącę i lojalnie przyznaję, że nie przeczytałem wszystkiego, ale... Kiedyś dawno temu też robiłem liczniki na plikach. Zawsze co jakiś czas się wszystko wysypywało niezależnie od zabezpieczeń, locków itd... Nie wiem czemu, ale PHP nie radzi sobie z tym zbyt dobrze. To mnie zmusiło do nauczenia się baz danych ;)

    Obecnie na plikach robię tylko takie rzeczy jak generowanie o północy jakiś "cache-plików", które później tylko odczytuję. Z odczytem problemów nie ma, natomiast zapis wykonywane przez jeden skrypt... Czasem się nie udaje i trzeba plik usunąć i ponownie odtworzyć (przy wielokrotnej próbie otwarcia do zapisu ciągle zwraca błąd). Nie ma tylko problemu, jeśli skrypt jest uruchamiany z poziomu konta roota (a ściślej - przez cronjob).

    0
  • #12 05 Lut 2014 17:45
    arnoldziq
    Moderator Programowanie

    Nie, no spoko.
    Tylko, że autor tematu nie wspomniał ani słowem o bazie danych i nawet nie wiadomo czy ma do takowej dostęp.

    0
  • #13 05 Lut 2014 17:49
    11111olo
    Poziom 43  

    To skoro zapis do pliku jest mało pewny, jak to rozwiązać za pomocą bazy MySQL?
    W tym przypadku jestem całkiem zielony.

    0
  • Pomocny post
    #14 05 Lut 2014 18:09
    arnoldziq
    Moderator Programowanie

    Z tym "mało pewny" to bym nie przesadzał.
    Od lat mam kilkadziesiąt tego typu liczników poustawianych na wielu stronach i jakoś się nigdy z żadnym takim problemem jak twój nie spotkałem.
    Ale za licznikiem na bazie danych przemawia to, że odchodzą Ci problemy związane z blokowaniem plików. Także odczyt i zapis danych jest dużo bezpieczniejszy.
    Tak na szybko:
    1. Robisz w bazie tabelę zawierającą nazwę strony i ilość wystąpień.

    Kod: mysql
    Zaloguj się, aby zobaczyć kod

    2. Przy otwarciu skryptu na stronie wywołujesz SQL-a który przeczyta obecny stan licznika.
    Kod: mysql
    Zaloguj się, aby zobaczyć kod

    2. Drugi SQL który zapisze lub utworzy nowy rekord i zwiększoną o 1 wartość ilości wywołań.
    Kod: mysql
    Zaloguj się, aby zobaczyć kod

    0
  • #15 05 Lut 2014 18:19
    11111olo
    Poziom 43  

    To co napisałeś nie wygląda na skomplikowane ale jak to czytam to tak jakby to była chińszczyzna :D

    Mam bazę danych MYSQL na której stoi forum. Wiem że da się dodać folder czy jakoś tak dla kolejnej bazy jednak zupełnie nie wiem jak to zrobić :(

    0
  • #16 05 Lut 2014 18:43
    arnoldziq
    Moderator Programowanie

    Dobra :)
    Kody są wycięte, na żywca z jednego z moich projektów, więc będziesz musiał dopracować szczegóły.

    Plik config.php

    Spoiler:
    Kod: php
    Zaloguj się, aby zobaczyć kod
    Plik database.php
    Spoiler:
    Kod: php
    Zaloguj się, aby zobaczyć kod
    Plik install.php
    Spoiler:
    Kod: php
    Zaloguj się, aby zobaczyć kod

    Zapisz pliki gdzieś na stronie z odpowiednimi nazwami.
    Wstaw odpowiednie dane w pliku config.php.
    Następnie uruchom przez przeglądarkę install.php.

    To stworzy odpowiednią tabelę w bazie danych.
    Jutro, na szybko, stworzę jakiś skrypt, który będzie zapisywał do tej bazy dane.

    0
  • Pomocny post
    #17 06 Lut 2014 12:01
    arnoldziq
    Moderator Programowanie

    Tak jak obiecałem.

    Plik config.php:

    Spoiler:
    Kod: php
    Zaloguj się, aby zobaczyć kod
    Plik database.php:
    Spoiler:
    Kod: php
    Zaloguj się, aby zobaczyć kod
    Plik install.php:
    Spoiler:
    Kod: php
    Zaloguj się, aby zobaczyć kod
    Plik licznik.php:
    Spoiler:
    Kod: php
    Zaloguj się, aby zobaczyć kod


    Plik test.php albo dowolna inna nazwa:
    Kod: php
    Zaloguj się, aby zobaczyć kod

    Zamieściłem ponownie wszystkie pliki, bo dokonałem niewielkich zmian w ich zawartości.
    Tak jak pisałem w poprzednim poście:
    1. Zapisać wszystkie pliki pod odpowiednimi nazwami.
    2. Uruchomić install.php, żeby utworzyć bazę i tabelę.
    3. Uruchomić plik test.php w celu testu.
    4. Wkleić zawartość pliku test.php w dowolnym miejscu na stronie.

    Funkcja IleRazy() wyświetli w trybie tekstowym cyferkę odpowiadającą ilości poprzednich odwiedzin konkretnej strony, z której została wywołana.

    PS.: Zapytanie SQL typu 'REPLACE INTO' jest właściwe dla MySQL-a w wersji 5.0+. Jeżeli ktoś będzie używał wcześniejszej wersji, zapytanie trzeba zmienić.

    0
  • #18 06 Lut 2014 14:04
    11111olo
    Poziom 43  

    Przeanalizowałem co napisałeś i nie jestem do końca pewny czy wszystko jest poprawnie napisane.

    Kod: php
    Zaloguj się, aby zobaczyć kod


    Czyli można skorzystać tylko z jednego licznika?
    A jeśli dodałbym inną tabelę o nazwie odwiedziny to czy odczyta z tabeli odwiedziny czy licznik?

    Kod: php
    Zaloguj się, aby zobaczyć kod


    To oznacza tworzenie nowej tabeli o zakresie liczby Integer?
    Jeśli tak to trochę mało bo 32768 odświeżenie konkretnej podstrony będzie wartością ujemną.
    Czy nie powinno być real?

    Kod: php
    Zaloguj się, aby zobaczyć kod


    Ja aby odczytać nazwę pliku odwiedzonej strony stosuję

    Kod: php
    Zaloguj się, aby zobaczyć kod


    Czy na pewno to zadziała?
    Nie chciałbym aby za każdym razem każda strona była identyfikowana jako index.

    0
  • Pomocny post
    #19 06 Lut 2014 15:08
    arnoldziq
    Moderator Programowanie

    11111olo napisał:
    Przeanalizowałem co napisałeś i nie jestem do końca pewny czy wszystko jest poprawnie napisane.
    Mam wracać z powrotem do szkoły? :(
    11111olo napisał:
    Czyli można skorzystać tylko z jednego licznika?
    Nie rozumiem.
    11111olo napisał:
    A jeśli dodałbym inną tabelę o nazwie odwiedziny to czy odczyta z tabeli odwiedziny czy licznik?
    Zapytanie SQL odczyta dane z tabeli którą wskażesz. Słowo po 'FROM' to jest właśnie nazwa tabeli z której chcemy czytać.
    11111olo napisał:
    To oznacza tworzenie nowej tabeli o zakresie liczby Integer?Jeśli tak to trochę mało bo 32768 odświeżenie konkretnej podstrony będzie wartością ujemną.
    Liczba INTEGER przyjmuje wartości od -32... do +32... dla wartości 16 bitowych. Od kiedy mamy procesory 32 (a nawet 64) bitowe, "zasięg" liczby integer zmienił się dość znacznie.
    Zapewniam, że wystarczy "miejsca".
    11111olo napisał:
    Ja aby odczytać nazwę pliku odwiedzonej strony stosuję
    Ależ ja nie bronię przed stosowaniem czegokolwiek kolega sobie zażyczy.
    Napisałem to tak, żeby działało na XAMPP-ie i serwerach elektrody. I działa. Reszta, to już zależy wyłącznie od kolegi.
    11111olo napisał:
    Nie chciałbym aby za każdym razem każda strona była identyfikowana jako index.
    Nic nie wiem na ten temat.

    0
  • #20 07 Lut 2014 11:10
    11111olo
    Poziom 43  

    Temat lekko przeciągnę ponieważ możliwe że dziś będę miał więcej baz MYSQL i próby z licznikiem zrobimy na osobnej bazie.

    0
  • #21 07 Lut 2014 11:17
    arnoldziq
    Moderator Programowanie

    Ale po co?
    Jedna baza to więcej niż potrzeba. Zawsze możesz całą tabelę usunąć, jak Ci coś nie "zapasuje".

    0
  • #22 07 Lut 2014 11:20
    11111olo
    Poziom 43  

    A po to bo jak coś pójdzie nie tak (niekoniecznie z Twojej winy) to będę bawił się w przywracanie kopii itp. a tam na nowej bazie nie będę się o to martwił.
    I tak będzie ich pięć więc czemu nie wykorzystać innej?

    -----------------------------
    EDIT

    Wychodzi że działa.
    Tworzenie nowej bazy coś nie działa więc zrobiłem to ręcznie.
    Tabelka się utworzyła choć zmieniłem nazwę na inną.

    Zmieniłem INT na REAL.

    Chcę jeszcze zrobić to samo ale z licznikiem pobrań.

    Zrobienie nowej tabelki to nie problem jak i odwołań i najlepiej jak to wszystko umieszczę w innym folderze?

    Nie dało by się zrobić że jak nie ma odświeżeń bo ktoś pierwszy raz wejdzie na stronę to jest zero.

    0
  • #23 07 Lut 2014 20:13
    arnoldziq
    Moderator Programowanie

    11111olo napisał:
    Zmieniłem INT na REAL.
    Kompletnie bez sensu.
    11111olo napisał:
    Zrobienie nowej tabelki to nie problem jak i odwołań i najlepiej jak to wszystko umieszczę w innym folderze?
    Jeżeli korzystasz z bazy danych, to taka zmiana zupełnie nie ma sensu. Każdy folder będzie dobry. Nawet główny.
    11111olo napisał:
    Nie dało by się zrobić że jak nie ma odświeżeń bo ktoś pierwszy raz wejdzie na stronę to jest zero.
    Oczywiście, że byłoby można.
    Zmień :
    Kod: php
    Zaloguj się, aby zobaczyć kod
    na:
    Kod: php
    Zaloguj się, aby zobaczyć kod

    0
  • #25 08 Lut 2014 10:58
    arnoldziq
    Moderator Programowanie

    11111olo napisał:
    To jeszcze napisz jak zrobić aby dla każdej podstrony zapisać ilość wyświetleń.

    Jak to "jak"?
    Przecież takie było założenie tego projektu od samego początku :/
    Wystarczy include-ować "licznik.php" i uruchomić funkcję ileRazy() z dowolnej pod-strony, żeby stworzyć osobny licznik tylko dla tej strony.

    0
  • #26 09 Lut 2014 11:27
    11111olo
    Poziom 43  

    Dodałem to do strony i działa, jednak nie podobają mi się same wpisy.

    Wydaje mi się, że zmiana

    Kod: php
    Zaloguj się, aby zobaczyć kod

    na
    Kod: php
    Zaloguj się, aby zobaczyć kod

    powinna rozwiązać mój problem.

    Co do wyświetlania wsteczności licznika wystarczy zapisać
    Kod: php
    Zaloguj się, aby zobaczyć kod

    zamiast
    Kod: php
    Zaloguj się, aby zobaczyć kod


    Teraz jeszcze wyjaśnij mi jak za pomocą funkcji readile i writeile zapisać coś do zupełnie innego rekordu tej samej kolumny (zamiast odwiedzin miałoby to być pobran)?

    0
  • #27 09 Lut 2014 11:44
    arnoldziq
    Moderator Programowanie

    11111olo napisał:
    Wydaje mi się, że zmiana
    Kod: php
    Zaloguj się, aby zobaczyć kod
    na
    Kod: php
    Zaloguj się, aby zobaczyć kod
    powinna rozwiązać mój problem.

    Spróbuj i zobaczysz. To twoja strona i nie potrzebujesz mojego zezwolenia czy aprobaty, żeby dokonać na swojej stronie dowolnych zmian.

    11111olo napisał:
    Co do wyświetlania wsteczności licznika wystarczy zapisać
    Kod: php
    Zaloguj się, aby zobaczyć kod

    zamiast
    Kod: php
    Zaloguj się, aby zobaczyć kod


    To co piszesz, to jakaś zupełna bzdura.
    Taki zapis pokaże stan licznika wliczając obecne "odwiedzenie". Jaki to ma sens? Wchodzisz na "nową" stronę i pokazuje Ci '1'? Chcesz wiedzieć ile osób poprzednio odwiedziło tę stronę, czy chcesz się pokazać własne odwiedziny?
    Nie łapię tego.
    11111olo napisał:
    Teraz jeszcze wyjaśnij mi jak za pomocą funkcji readile i writeile zapisać coś do zupełnie innego rekordu tej samej kolumny (zamiast odwiedzin miałoby to być pobran)?

    Nie bardzo rozumiem, co ma licznik odwiedzin wspólnego z licznikiem pobrań.
    Można to zrobić, tylko trzeba założyć osobną tabelę z odrobinę inną zawartością.
    Poza tym, chyba nie wystarczy wywoływać losowo tych procedur. Trzeba te pobrania jakoś z tym powiązać, prawda?

    0
  • #28 09 Lut 2014 12:19
    11111olo
    Poziom 43  

    arnoldziq napisał:
    Nie bardzo rozumiem, co ma licznik odwiedzin wspólnego z licznikiem pobrań.
    Można to zrobić, tylko trzeba założyć osobną tabelę z odrobinę inną zawartością.
    Poza tym, chyba nie wystarczy wywoływać losowo tych procedur. Trzeba te pobrania jakoś z tym powiązać, prawda?

    Teoretycznie wystarczyłoby podpiąć za pomocą include tą samą funkcję licznik i by zadziałało, tylko, że wtedy zrobiłby się niezły śmietnik.
    Jeśli dodam drugą tabelę o nazwie pobrań to aby skorzystać z funkcji readile i writeile muszę i tak na nowo napisać funkcje lub zmodyfikować jakoś 2 wiersze - po jednym w funkcjach readile i writeile.
    Kod: php
    Zaloguj się, aby zobaczyć kod

    Moim zdaniem pisząc te dwie funkcje powinieneś dodać jeszcze jeden parametr określający nazwę tabeli do której odwołuje się odczyt i zapis.
    Wyglądałoby to na zasadzie
    Kod: php
    Zaloguj się, aby zobaczyć kod

    Moim zdaniem taki odczyt i zapis będzie bardziej uniwersalny i praktyczny.
    Doceniam Twój trud włożony w napisanie tego nieskomplikowanego sktryptu.

    0
  • #29 09 Lut 2014 12:25
    arnoldziq
    Moderator Programowanie

    11111olo napisał:
    Moim zdaniem pisząc te dwie funkcje powinieneś dodać jeszcze jeden parametr określający nazwę tabeli do której odwołuje się odczyt i zapis.
    Wyglądałoby to na zasadzie
    Kod: php
    Zaloguj się, aby zobaczyć kod
    Moim zdaniem taki odczyt i zapis będzie bardziej uniwersalny i praktyczny.
    Doceniam Twój trud włożony w napisanie tego nieskomplikowanego sktryptu.

    Skrypt został stworzony w jednym celu; przeniesienia licznika odwiedzin, z plików tekstowych do bazy danych.
    Skoro miała być w tym skrypcie wykorzystana tylko jedna tabela, to mówienie o jakiejkolwiek "uniwersalności" to chyba jakaś pomyłka.
    Jeżeli chce kolega wykorzystać ten kod do czegoś innego, to nic nie stoi na przeszkodzie, żeby kolega ten kod zmodyfikował zgodnie ze swoimi potrzebami.

    0
  • #30 09 Lut 2014 13:21
    11111olo
    Poziom 43  

    Z początku coś naknociłem ale teraz już działa.
    Wywołanie licznika jesli nie jest to strona główna (index.php).

    Kod: php
    Zaloguj się, aby zobaczyć kod

    Funkcja zwiększająca licznik określonej tabeli (licznik.php).
    Kod: php
    Zaloguj się, aby zobaczyć kod

    Odczyt i zapis do bazy (database.php).
    Kod: php
    Zaloguj się, aby zobaczyć kod

    Chyba już wszystko w tym temacie zostało napisane.
    Dzięki za pomoc.

    0