[PHP] Jak zablokować powtórne przetwarzanie formularzy przy odświeżaniu strony?
Chcesz zablokować przetwarzanie lub wysyłanie formularzy jeżeli ktoś będzie kilka razy przeładowywał w przeglądarce stronę WWW za pomocą guzika (reload/odśwież). Nie chcesz wielokrotnie przetwarzać formularza z tymi samymi danymi.
Blokada wielokrotnego przetwarzania formularzy to istotny element serwisu. Brak blokady może powodować niepotrzebne wysyłanie listów, wielokrotne dopisywanie informacji do baz danych, na forum, do księgi gości lub w innych skryptach.
Oto dwa sposoby poradzenia sobie z problemem: gotowa strona index.php, która za pomocą cookies blokuje wielokrotne przetwarzanie formularza i inne rozwiązanie z nagłówkiem przekierowującym.
<?
if (($napis<>"")and($ciacho<>$napis)) {
setcookie ("ciacho", $napis, 0);
// tutaj następuje obróbka formularza...
$wynik = "formularz został przetworzony: $napis";
}
?>
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html><head><meta http-equiv="content-type"
content="text/html; charset=iso-8859-2">
<title>tytuł strony</title></head><body>
<?
echo $wynik;
?>
<p>
<form action="index.php" method="get">
<input name="napis" type="text">
<input type="submit" value=" wyślij ">
</form>
</body></html>
Przykładowy formularz zawiera tylko jedno pole o nazwie "napis". Pól może być naturalnie znacznie więcej, jednak do skryptu blokującego musisz wybrać jedno pole, które zawsze będzie wypełnione przez użytkownika. Ewentualnie może to być pole ukryte (type="hidden"), wypełnione przez Ciebie.
Na samym początku strony ustawiane będzie ciasteczko (cookies), w którym znajdzie się informacja, czy skrypt przetworzył już formularz czy nie. Zapisanie cookies MUSI się odbywać na samym początku, zanim reszta strony zostanie wysłana do przeglądarki.
Sprawdzamy więc, czy nasze pole jest w ogóle wypełnione $napis<>"" i czy ustawione cookies o nazwie ciacho jest różne od wartości pola "napis". Jeżeli tak, to znaczy, że możemy przetwarzać formularz. Ustawiamy więc cookies na aktualną wartość pola "napis" i przetwarzamy formularz.
Jeżeli ktoś ponownie przeładuje stronę, wartość zmiennej $napis będzie różna od pustego łańcucha, a $ciacho (czyli nasze cookies) będzie miało wartość tego pola. Warunek nie będzie spełniony i formularz nie zostanie przetworzony.
Przy zmianie wartości pola "napis" w formularzu, można go przetwarzać ponownie - ma to sens, ponieważ użytkownik może pomylić się i potem sprostować informacje.
Całość sprawuje się bardzo dobrze pod warunkiem, że użytkownik nie wyłączył obsługi cookies w przeglądarce. Zdecydowana większość użytkowników ma jednak włączone cookies, a biorąc pod uwagę fakt, że jednak niewiele osób próbuje przeładowywać stronę, mamy 99% proc. pewności, że problem wielokrotnego przetwarzania tych samych formularzy jest rozwiązany.
Drugi sposób jest nieco inny, ale kod też musi się znaleźć na początku strony (reszta jak w pierwszym przykładzie):
<?
if ($napis<>"") {
// tutaj następuje obróbka formularza...
$f=fopen("log.txt","a"); fputs($f,"$napis\n"); fclose($f);
header("Location: index.php");
}
?>
Jeżeli pole ma jakąś wartość, następuje przetworzenie formularza (w naszym wypadku dopisanie wartości pola do pliku tekstowego) i przekierowanie na tą samą stronę, ale bez parametrów - tak, jakby formularz nie był wypełniony.
Drugie rozwiązanie nie jest tak eleganckie i wszechstronne, ale nie jest zależne od cookies, co czasem może mieć znaczenie. Pierwszy sposób pozwala również na pokazanie zawartości formularza po przeładowaniu, co często bywa dosyć istotną sprawą z punktu widzenia wygody i interakcji z użytkownikiem.