to moze i ja dorzuce swoje 3 grosze.
# rozwiazanie w stylu js/ajax jest moim zdaniem chybione, bo po co wogole angazowac ajaxa do rzeczy tak banalnej jak wyslanie formularza.
# rozwiazanie z dodawaniem ukrytego pola do formularza po kliknieciu submit w formularzu tez nie bedzie dzialalo, bo klikniecie F5 powoduje wyslanie ponownie TEGO SAMEGO formularza, wiec nie zostanie wyslany nowy z nowo wygenerowanym polem - a chodzi tutaj chyba o zabezpieczenie przez refresh'em a nie ponownym klikaniem w submit.
kolega wczesniej podawal przyklad:
<?php
if(isset($_POST['AddReply']) && !isset($_POST['Re'])) $class->AddReply(); ?>
a w forumularzu:
<form action="" method="post">
<?php if(!empty($_POST)) echo '<input name="Re" type="hidden" value="1">'; ?> <input name="AddReply" type="hidden" value="1">
...
</form>
i tak jak napisalem to oczywiscie nie dziala, bo klikniecie F5 (refresh) nie powoduje ponownej generacji formularza czyli pole
<input name="Re" type="hidden" value="1">
nie zostanie wyslane z formularzem
# rozwiazanie z zapisywaniem IP oraz czasu i sprawdzanie czy nowy post jest z tego samego IP co ostatni, jesli tak to ile minelo czasu - jest rowniez niepoprawne. po pierwsze co jesli dodaje dwa posty w roznych topicach w bardzo krotkim czasie? z tym oczywiscie mozna sobie poradzic, bo mozna sprawdzac czy nowy post jest z tego samego topicu czy nie, ale na jakiej zasadzie ma byc liczony czas po ktorym mozna ponownie dodac posta? 60 sekund jak zaproponowal kolega wyzej? to klikne F5 po 65 sekundach. 120 sekund? to klikne F5 po 125 sekundach? 240 sekund? itd. To rozwiazanie moze byloby i dobre, ale na calkowicie inny problem. Na spamerow, trolli czy inne typu wynalazki, czyli zablokowanie mozliwosci wysylanie duzej ilosci postow przez tego samego uzytkownika w krotkim czasie. Ale bynajmniej nie jest to rozwiazanie na refresh o ktory sie w tym topicu rozchodzi.
# rozwiazanie z przechwytywaniem wyjatkow z bazy owszem dziala, ale tylko jesli zapisujemy tresc formularza do bazy. a co jesli ma byc zapisywany do pliku, wyslany mailem, czy cokolwiek innego ma sie z nim dziac?
# rozwiazanie z dodawaniem atrybutow UNIQUE do pol bazy zadziala jak wyzej - tylko w przypadku, gdy dane z formularza maja wyladowac w bazie.
Wiec jak to najlepiej zrobic i tak zeby dzialalo zawsze?
# jednym z rozwiazan jest to o czym zapewne wiekszosc z was wie. czyli przekierowanie w pliku do ktorego odwoluje sie akcja formularza.
jesli mamy formularz:
<form action="wykonaj_akcje.php"> ...
to w pliku wykonaj_akcje.php zapisujemy:
<?
//jakies akcje
header("Location: akcja_wykonana.php") ?>
# drugie rozwiazanie, ktore ja osobiscie najczesciej stosuje, jest to o czym pisal
nospor.
w momencie generowania formularza generujemy pole typu "hidden" z jakims hashem/tokenem czy jak tam kto woli nazywac. ma to byc jakis unikalny ciag znakow/liczb:
<input type="hidden" id="hash" name="hash" value="<?=generateHash();?>">
<?php
function generateHash()
{
return md5(time() * rand()); //samo time() nie wystarczy, gdyz jego wartosc zmienia sie co sekunde a to za malo }
?>
wartosc tego pola zapisujemy do sesji, do cookie, do pliku albo do bazy - jak komu w danej chwili wygodniej/jakie ma mozliwosci.
w przypadku zapisu da bazy tabela z postami bedzie miala dodatkowe pole "hash". po kliknieciu F5 (refresh) zostanie wyslany ten sam formularz, czyli dokladnie z tym samym hashem - nie bedzie on od nowa wygenerowany. teraz wystarczy sprawdzic czy dany hash mamy juz w sesji, w bazie, w cookie, w pliku czy gdziekolwiek indziej i problem z powtorzeniem zalatwiony
i tutaj juz nie chodzi o sprawdzenie czy to ten sam uzytkownik, to samo IP, ponownie ten sam tekst czy cokolwiek innego - sprawdzamy dokladnie to o co chodzi - czy jest proba ponownego wyslania tego samego formularza.