Po pierwsze - jest to napisane paskudnie. Rozumiem, że się dopiero uczysz, więc nie będę się znęcać, ale jedynie dam kilka rad:
- używaj bardziej opisowych zmiennych, bo kod z
$e, $fp, $u
itp. się fatalnie czyta. No i nie wiadomo, za co dana zmienna odpowiada, trzeba zaglądać wyżej, żeby sprawdzić, co zostało do niej podstawione
- w temacie nazw zmiennych i funkcji - staraj się używać angielskich słów. Oczywiście - program będzie tak samo działac (albo i nie ;) ) ale jest to taki przyjęty standard, w ten sposób kod wygląda o wiele bardziej profesjonalnie, a poza tym ułatwia się czytanie innym
- nie używaj tzw.
magicznych stałych
- zamiast napisać $czas = 24*60*60;
lepiej by było najpierw zadeklarować #godziny = 24; $minuty = 60; $sekundy = 60;
, a potem napisać coś w stylu $czas = $minuty * $godziny * $sekundy
.
- powinieneś to podzielić, bo na razie masz jeden wielki mix: wczytywanie pliku, przetwarzanie danych, wypluwanie na ekran itp. Tak się nie powinno działać. Nie bój się funkcji, one bardzo pomagają i zwiększają czytelność kodu.
- trzymanie tego w pliku tekstowym nie jest dobrym pomysłem, zainteresuj się SQLite. W necie jest pełno tutoriali jak się z tego korzysta, pierwszy z brzegu - http://zetcode.com/php/sqlite3/
Ostatni punkt jest także jest odpowiedzią na fragment by usuwał adresy IP które są dłużej niż 24h
- korzystając z SQL możesz przerzucić całą logikę na bazę, wywalić paskudne explode
. Tworzysz tabelę, w której trzymasz adres IP oraz tzw. timestamp
. Następnie podczas sprawdzenia robisz coś w stylu SELECT ID FROM daty_wpisow WHERE IP=xxxx
i patrzysz, czy dostaniesz jakiś wynik. Jeśli tak, to znaczy, że informacja w bazie o danym adresie istnieje. Jeśli nie, to dodajesz. W SQL możesz zrobić, żeby pole timestamp
się samo aktualizowało z wykorzystaniem aktualnego czasu, więc cała akcja z Twojej strony ogranicza się do wydania polecenia INSERT INTO daty_wposow (adres_ip) VALUES (xxxx);
gdzie xxxx
jest adresem IP, który chcesz zablokować na jakiś czas. A samo czyszczenie wpisów przeterminowanych będzie miało postać DELETE FROM daty_wpisow WHERE timestamp xxxx
i zamiast xxx
podajesz warunek, na podstawie którego wpisy mają zostać usunięte - np. że timestamp jest wcześniejszy niż 24h od teraz. Zobacz - Ty jedynie dajesz polecenie żeby usunąć wpisy o akcjach sprzed doby (albo spełniających jakikolwiek inny warunek), a całą robotę za Ciebie odwala SQL. Czy to nie jest piękne?
I ważna uwaga - nie bój się SQL. W powaznych zastosowaniach to jest kobyła, która wymaga niezłego skilla, ale w takich podstawowych rzeczach to jest dosłownie kilka linijek, które ogarniesz w 15 minut. Na pewno mniej będzie z tym problemów niż z tym, co pokazałeś powyżej ;)
EDIT
A odpowiadając na Twoje pytanie - taka pierwsza myśl to może być problem z równoczesnym dostępem do pliku. Zobacz https://www.php.net/manual/en/function.flock.php, a w szczególności te komentarze:
I've been having trouble getting Flock to work when I read a file, delete it, and then output slightly changed information back to the same location. When deleting with Unlink, there's a very brief period of time where no file exists. But, if you do an fopen using the "w" mode, it keeps the file in existence, but deletes all of its data when you go to write to it. That way, the file never actually disappears, and another script accessing the same file with flock won't get a "file doesn't exist" error.
oraz
I just spent some time (again) to understand why a reading with file_get_contents() and file was returning me an empty string "" or array() whereas the file was existing and the contents not empty.
In fact, i was locking file when writing it (file_put_contents third arg) but not testing if file was locked when reading it (and the file was accessed a lot).
So, please pay attention that file_get_contents(), file() and maybe others php files functions are going to return empty data like if the contents of the file was an empty string.
To avoid this problem, you have to set a LOCK_SH on your file before reading it (and then waiting if locked).
Być może czyszczenie się pliku wynika z tego, że gdzieś był zablokowany/miałeś włączony dostęp w trybie zapisu, potem starałeś się go odczytać, została odczytana pusta wartość, a następnie dodałeś nowa informację do pliku, który wydawał się pusty, więc jego zawartość została stracona. Tak mi przyszło do głowy. Sprawdź proszę, czy w takiej sytuacji o której piszesz - czyli że wpisy się zgubiły, cała zawartość pliku jest czyszczona, czy może plik jest OK, tylko nie udało się z niego wczytać danych i przez to skrypt nie odczytał informacji, że dany IP już występował.