Jak zapobiec ponownemu przesłaniu formularza po odświeżeniu strony (F5 / CTRL + R)


142

Mam prosty formularz, który przesyła tekst do mojej tabeli SQL. Problem w tym, że po przesłaniu tekstu przez użytkownika może odświeżyć stronę i dane są przesyłane ponownie bez ponownego wypełniania formularza. Mogę przekierować użytkownika na inną stronę po przesłaniu tekstu, ale chcę, aby użytkownicy pozostali na tej samej stronie.

Pamiętam, że przeczytałem coś o nadaniu każdemu użytkownikowi unikalnego identyfikatora sesji i porównaniu go z inną wartością, która rozwiązała problem, który mam, ale zapomniałem, gdzie on jest.



1
Dlaczego nie chcesz przekierowywać użytkownika na inną stronę?
Adam

@Adam: Ponieważ to przesada, aby wykonać kolejne żądanie do serwera, który z kolei ponownie pobierze dane z DB. Ale to marnowanie zasobów, ponieważ już pobieramy wszystkie wymagane dane podczas przetwarzania POSTżądania
Eugen Konkov

@EugenKonkov we wzorcu PRG, po prostu przekierowałbyś do strony, która pokazuje komunikat o sukcesie. Nie jest potrzebne dalsze pobieranie z DB.
Adam

@Adam: Możesz także wyświetlić cały rekord, który jest tworzony przez POSTdane. W takim przypadku potrzebujesz SELECTgo od DB. Na przykład, kiedy tworzysz fakturę, zostajesz przekierowany, na /invoices/53którym wyświetlana jest cała faktura zamiast tylko
``

Odpowiedzi:


102

Użyj wzorca Post / Redirect / Get. http://en.wikipedia.org/wiki/Post/Redirect/Get

W mojej witrynie zapiszę wiadomość w pliku cookie lub sesji, przekieruję po poście, przeczytam plik cookie / sesję, a następnie wyczyszczę wartość tej sesji lub zmiennej cookie.


1
To sprawia, że ​​Chrome nie nadaje się do programowania, gdzie biznes wymaga tylko postu!
John Peters,

27
Jeśli korzystasz ze wzoru PRG, to faktycznie opuszczasz stronę, prawda? Czy nie chodziło o to, jak sprawić, by wszystko działało bez przekierowywania?
Adam

1
Wydaje mi się, że jeśli przekierowujesz na tę samą stronę, to $ _POST jest wyczyszczone. Jak rozumiem, to był pożądany efekt. W każdym razie to był MÓJ pożądany efekt. Myślę jednak, że odpowiedź byłaby lepsza, gdyby była to wyraźna.
donutguy640

Działa dobrze, moim jedynym zaleceniem jest włączenie ścisłego testowania błędów, aby wykryć błędy lokalnie podczas programowania, w przeciwnym razie mogą pozostać niezauważone.
Maurice

Nie odpowiada na pytanie. Nie wiem, dlaczego jest to akceptowana odpowiedź.
YungGun

139

Chciałbym również zwrócić uwagę, że możesz użyć podejścia javascript, window.history.replaceStateaby zapobiec ponownemu przesłaniu po naciśnięciu przycisku odświeżania i powrotu.

<script>
    if ( window.history.replaceState ) {
        window.history.replaceState( null, null, window.location.href );
    }
</script>

Dowód koncepcji tutaj: https://dtbaker.net/files/prevent-post-resubmit.php

Nadal polecałbym podejście Post / Redirect / Get, ale jest to nowatorskie rozwiązanie JS.


1
Dzięki, @dtbaker, jest super :)
Gufran Hasan,

1
Tks, to działa idealnie dla mnie, wystarczyło utworzyć stronę 404, aby uniknąć
niezrozumienia przez

Po prostu niesamowite. Dziękuję
user4906240

2
nie działa w safari, zmieniło href, ale nadal zachowuje dane z prośbą o przesłanie
Vo Thanh Tung

To zadziałało dla mnie, dziękuję! Dlaczego polecacie podejście PRG?
iJassar

16

Naprawdę powinieneś użyć wzorca Post Redirect Get do obsługi tego, ale jeśli w jakiś sposób znalazłeś się w pozycji, w której PRG nie jest opłacalne (np. Sam formularz jest zawarty w dołączaniu, zapobiegając przekierowaniom), możesz zaszyfrować niektóre parametry żądania utworzyć ciąg znaków na podstawie zawartości, a następnie sprawdzić, czy jeszcze go nie wysłałeś.

//create digest of the form submission:

    $messageIdent = md5($_POST['name'] . $_POST['email'] . $_POST['phone'] . $_POST['comment']);

//and check it against the stored value:

    $sessionMessageIdent = isset($_SESSION['messageIdent'])?$_SESSION['messageIdent']:'';

    if($messageIdent!=$sessionMessageIdent){//if its different:          
        //save the session var:
            $_SESSION['messageIdent'] = $messageIdent;
        //and...
            do_your_thang();
    } else {
        //you've sent this already!
    }

Dzięki za udostępnienie, ale to nie działa. Odświeżenie strony rzeczywiście powoduje ponowne przesłanie formularza za mnie. Może czegoś mi brakuje?
aLearner

Odświeżenie strony spowoduje ponowne przesłanie wszystkiego, ale zdecydujemy się na przetwarzanie danych zgłoszeniowych tylko wtedy, gdy będą się one różnić od ostatnio przesłanych (które przechowujemy w sesji var 'messageIdent'). Czy przetwarzasz przesłanie formularza w ramach klauzuli „if messageIdents are different” (tj. Gdzie jest „do_your_thang ()”)?
Moob

Dzięki za odpowiedź. Skończyło się na tym, że zaimplementowałem wzorzec Post / Redirect / Get, więc nie pamiętam teraz, co dokładnie mnie potknęło. Jeszcze raz dziękuję za przybycie.
aLearner

Ta metoda nie ma na celu blokowania ponownego przesłania… ale służy do wykrywania ponownego przesłania, aby można było zmienić kod tak, aby nie „robił” tego, co zrobiłbyś, gdyby było to nowe zgłoszenie. Innymi słowy: za pomocą tej metody można wykryć „oryginalne” przesłanie i umieścić swoje dane. Jeśli NIE jest oryginalny, nie umieszczaj swoich danych. Albo pokaż ostrzeżenie o „próbie oszustwa”, albo może zamiast tego pokaż „potwierdzenie”.
TheSatinKnight,

Aby to zadziałało, musisz rozpocząć sesję, dodając session_start();na początku pliku. w3schools.com/php/php_sessions.asp mówi Uwaga: Funkcja session_start () musi być pierwszą rzeczą w dokumencie. Przed jakimikolwiek tagami HTML.
wkille

16

Używam tej linii javascript do blokowania wyskakującego okienka z prośbą o ponowne przesłanie formularza przy odświeżaniu po przesłaniu formularza.

if ( window.history.replaceState ) {
  window.history.replaceState( null, null, window.location.href );
}

Po prostu umieść tę linię w stopce pliku i zobacz magię


Byłaby fajna wersja tego, której nie można wyłączyć po stronie klienta, ale jest krótka, łatwa, szybka ... i robi to, co trzeba. Zachowuje historię, aby użytkownik mógł przejść wstecz bez ponownego wysyłania postów.
Péter Vértényi

16

Możesz zapobiec ponownemu przesyłaniu formularzy za pomocą zmiennej sesji.

Najpierw musisz ustawić rand()w polu tekstowym i $_SESSION['rand']na stronie formularza:

<form action="" method="post">
  <?php
   $rand=rand();
   $_SESSION['rand']=$rand;
  ?>
 <input type="hidden" value="<?php echo $rand; ?>" name="randcheck" />
   Your Form's Other Field 
 <input type="submit" name="submitbtn" value="submit" />
</form>

Następnie sprawdź $_SESSION['rand']z $_POST['randcheck']wartością pola tekstowego w ten sposób:

if(isset($_POST['submitbtn']) && $_POST['randcheck']==$_SESSION['rand'])
{
    // Your code here
}

3
możemy użyć <input type="hidden" name="randcheck" id="randcheck" value="<?php echo microtime(); ?>" />zamiast tego
Nikolay Bronskiy

Tak, możemy użyć zarówno microtime (), jak i time () zamiast rand (), niezależnie od funkcji lub zmiennej, która daje inną wartość, możemy jej użyć. ALE upewnij się, że ustawiłeś tę wartość na zmienną SESSION. tutaj SESJA musi sprawdzić pole randcheck i uniemożliwić ponowne przesłanie formularza.
Savoo,

czy zmienna sesji nie powinna zostać wyczyszczona po sprawdzeniu, czy sesja i zmienna post są zgodne?
denoise

1
@denoise Uważam, że pomysł @Savoo polega na tym, że po $_POSTdanych formularza ta sama strona ładuje się ponownie, ustawiając sesję i wysyłając zmienne. Również tworzenie zmiennych powinno odbywać się po sprawdzeniu zgodności zmiennych. Dlatego unsetnie jest potrzebne.
Hmerman6006

13

Gdy formularz jest przetwarzany, przekierowujesz na inną stronę:

... process complete....
header('Location: thankyou.php');

możesz również przekierować na tę samą stronę.

jeśli robisz coś w rodzaju komentarzy i chcesz, aby użytkownik pozostał na tej samej stronie, możesz użyć Ajax do obsługi przesyłania formularza


12

Znalazłem następne obejście. Możesz uniknąć przekierowania po przetworzeniu POSTżądania, manipulując historyobiektem.

Masz więc formularz HTML:

<form method=POST action='/process.php'>
 <input type=submit value=OK>
</form>

Kiedy przetwarzasz ten formularz na swoim serwerze, zamiast przekierowywać użytkownika /the/result/page, ustawiając Locationnagłówek w następujący sposób:

$cat process.php
<?php 
     process POST data here
     ... 
     header('Location: /the/result/page');
     exit();
?>

wprowadź opis obrazu tutaj

Po przetworzeniu POSTdanych ed renderujesz małe <script>i wynik/the/result/page

<?php 
     process POST data here
     render the <script>         // see below
     render `/the/result/page`   // OK
?>

<script>Należy uczynić:

<script>
    window.onload = function() {
        history.replaceState("", "", "/the/result/page");
    }
</script>

Wynik to:

wprowadź opis obrazu tutaj

jak widać dane formularza są POSTedytowane do process.phpskryptu.
Ten skrypt przetwarza POSTdane ed i renderuje /the/result/pagejednocześnie za pomocą:

  1. brak przekierowania
  2. brak POSTdanych po odświeżeniu strony (F5)
  3. nie więcej, POSTgdy przechodzisz do poprzedniej / następnej strony w historii przeglądarki

UPD

Innym rozwiązaniem jest poproszenie zespołu Mozilla FireFox o umożliwienie użytkownikom skonfigurowania NextPagenagłówka, który będzie działał jak Locationnagłówek i sprawi, że post/redirect/getwzorzec stanie się przestarzały.

W skrócie. Gdy serwer POSTpomyślnie przetworzy dane formularza, to:

  1. NextPageNagłówek konfiguracji zamiastLocation
  2. Renderuj wynik przetwarzania POSTdanych formularza tak, jak byłby renderowany na GETżądanie we post/redirect/getwzorcu

Przeglądarka z kolei, gdy zobaczy NextPagenagłówek:

  1. Dostosuj za window.locationpomocą NextPagewartości
  2. Gdy użytkownik odświeży stronę, przeglądarka będzie negocjować GETżądanie NextPagezamiast zmieniać POSTdane

Myślę, że byłoby to doskonałe, gdyby zostało wdrożone, prawda? =)


11
  1. Użyj nagłówka i przekieruj stronę.

    header("Location:your_page.php"); Możesz przekierować na tę samą lub inną stronę.

  2. Cofnij ustawienie $ _POST po wstawieniu go do bazy danych.

    unset($_POST);


54
Cofnięcie ustawienia $ _POST w ogóle nie wpływa na ponowne przesłanie formularza, przynajmniej nie w Chrome.
Gavin

2
To nie zadziała. Gdy użytkownik wróci do poprzedniej strony, ponownie ustawia zmienne POST.
Sandhu

Jaki jest powód używania unset? Dodaj wyjaśnienie do swojej odpowiedzi, aby inni mogli się z niej nauczyć
Nico Haase

8

Ta metoda działa dla mnie dobrze i myślę, że jest to najłatwiejsza do wykonania tej pracy.

Ogólną ideą jest przekierowanie użytkownika na inne strony po przesłaniu formularza, co zatrzymałoby ponowne przesłanie formularza po odświeżeniu strony. Jeśli jednak potrzebujesz zatrzymać użytkownika na tej samej stronie po przesłaniu formularza, możesz to zrobić na wiele sposobów, ale tutaj opiszę metodę javascript.

Metoda Javascript

Ta metoda jest dość prosta i blokuje wyskakujące okienko z prośbą o ponowne przesłanie formularza przy odświeżaniu po przesłaniu formularza. Po prostu umieść tę linię kodu javascript w stopce pliku i zobacz magię.

<script>
if ( window.history.replaceState ) {
  window.history.replaceState( null, null, window.location.href );
}
</script>


To też mi pomaga
Ankit

7

Całkiem pewnym sposobem jest zaimplementowanie unikalnego identyfikatora do postu i umieszczenie go w pamięci podręcznej w pliku

<input type='hidden' name='post_id' value='".createPassword(64)."'>

Następnie w swoim kodzie zrób to:

if( ($_SESSION['post_id'] != $_POST['post_id']) )
{
    $_SESSION['post_id'] = $_POST['post_id'];
    //do post stuff
} else {
    //normal display
}

function createPassword($length)
{
    $chars = "abcdefghijkmnopqrstuvwxyz023456789";
    srand((double)microtime()*1000000);
    $i = 0;
    $pass = '' ;

    while ($i <= ($length - 1)) {
        $num = rand() % 33;
        $tmp = substr($chars, $num, 1);
        $pass = $pass . $tmp;
        $i++;
    }
    return $pass;
}

Właściwie właśnie napisałem coś podobnego do tego, ale nie zadałem sobie trudu, aby utworzyć hasło, po prostu wyliczyłem moje formularze (np .: kroki 1-5), więc jeśli są równe, fajnie jest przejść dalej, inaczej nie zapisuj do bazy danych ani nie wysyłaj e-maili. Ale pozwól użytkownikowi wylądować tam, gdzie go zaprowadzi.
Fernando Silva

1
Myślę, że jest to lepsze rozwiązanie niż ponowne załadowanie strony, ponieważ po pomyślnym wysłaniu wiadomości pokazuję wiadomość, a ponowne załadowanie strony spowoduje usunięcie wiadomości. to działa jak dla mnie, możesz też użyć unikalnego
Julio Popócatl

5

Javascript

Ta metoda jest dość prosta i blokuje wyskakujące okienko z prośbą o ponowne przesłanie formularza przy odświeżaniu po przesłaniu formularza. Po prostu umieść tę linię kodu javascript w stopce pliku i zobacz magię.

<script>
    if ( window.history.replaceState ) {
        window.history.replaceState( null, null, window.location.href );
    }
</script>

3

Po prostu przekieruj go na tę samą stronę po użyciu danych formularza i działa. Próbowałem tego.

header('location:yourpage.php');

4
To tylko powtórzenie tej samej odpowiedzi, którą ktoś inny udzielił wiele lat wcześniej. (W rzeczywistości dwóch innych!)
Nick Rice,

Jeśli powielasz odpowiedzi innych osób, powinieneś przynajmniej dodać wyjaśnienie do swojej odpowiedzi, aby była interesująca
Nico Haase

3

Udoskonalona wersja postu Mooba. Utwórz skrót POST, zapisz go jako plik cookie sesji i porównaj skróty w każdej sesji.

// Optionally Disable browser caching on "Back"
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Expires: Sun, 1 Jan 2000 12:00:00 GMT' );
header( 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT' );

$post_hash = md5( json_encode( $_POST ) );

if( session_start() )
{
    $post_resubmitted = isset( $_SESSION[ 'post_hash' ] ) && $_SESSION[ 'post_hash' ] == $post_hash;
    $_SESSION[ 'post_hash' ] = $post_hash;
    session_write_close();
}
else
{
    $post_resubmitted = false;
}

if ( $post_resubmitted ) {
  // POST was resubmitted
}
else
{
  // POST was submitted normally
}

2

Zasadniczo musisz przekierować z tej strony, ale nadal może to powodować problem, gdy twój internet jest wolny (nagłówek przekierowania z serwera)

Przykład podstawowego scenariusza:

Kliknij dwukrotnie przycisk przesyłania

Sposób na rozwiązanie

  • Strona klienta

    • Wyłącz przycisk przesyłania po kliknięciu go przez klienta
    • Jeśli używasz Jquery: Jquery.one
    • Wzór PRG
  • Po stronie serwera

    • Używanie sygnatury czasowej / sygnatury czasowej opartej na różnicowaniu, kiedy żądanie zostało wysłane.
    • Użyj żetonów żądań. Gdy główny ładuje się, przypisz tymczasowe żądanie tocken, które w przypadku powtórzenia jest ignorowane.

2

Jak zapobiec ponownemu przesyłaniu formularza php bez przekierowania. Jeśli używasz $ _SESSION (po session_start) i formularza $ _POST, możesz zrobić coś takiego:

if ( !empty($_SESSION['act']) && !empty($_POST['act']) && $_POST['act'] == $_SESSION['act'] ) {
  // do your stuff, save data into database, etc
}

W formularzu HTML umieść to:

<input type="hidden" id="act" name="act" value="<?php echo ( empty($_POST['act']) || $_POST['act']==2 )? 1 : 2; ?>">
<?php
if ( $_POST['act'] == $_SESSION['act'] ){
    if ( empty( $_SESSION['act'] ) || $_SESSION['act'] == 2 ){
        $_SESSION['act'] = 1;
    } else {
        $_SESSION['act'] = 2;
    }
}
?>

Tak więc za każdym razem, gdy przesyłany jest formularz, generowany jest nowy akt, zapisywany w sesji i porównywany z aktem post.

Ps: jeśli używasz formularza Get, możesz łatwo zmienić wszystkie POST za pomocą GET i to też działa.


1

Po wstawieniu go do bazy danych wywołaj metodę unset (), aby wyczyścić dane.

nieustawiony ($ _ POST);

Aby zapobiec odświeżaniu wstawiania danych, wykonaj przekierowanie strony na tę samą lub inną stronę po wstawieniu rekordu.

nagłówek ('Lokalizacja:'. $ _ SERVER ['PHP_SELF']);


1
Dodaj wyjaśnienie do swojej odpowiedzi, aby inni mogli się z niej nauczyć - dlaczego to unsetwezwanie jest potrzebne? Co by się stało, gdybyś to pominął?
Nico Haase

0

Użycie wzorca Post / Redirect / Get z odpowiedzi Keverw jest dobrym pomysłem. Nie jesteś jednak w stanie pozostać na swojej stronie (a myślę, że o to prosiłeś?) Ponadto czasami może się nie udać :

Jeśli użytkownik sieciowy odświeża się przed zakończeniem początkowego przesyłania z powodu opóźnienia serwera, co skutkuje zduplikowanym żądaniem HTTP POST w niektórych klientach użytkownika.

Inną opcją byłoby zapisanie w sesji, jeśli tekst powinien zostać zapisany w bazie danych SQL w następujący sposób:

if($_SERVER['REQUEST_METHOD'] != 'POST')
{
  $_SESSION['writeSQL'] = true;
}
else
{
  if(isset($_SESSION['writeSQL']) && $_SESSION['writeSQL'])
  {
    $_SESSION['writeSQL'] = false;

    /* save $_POST values into SQL */
  }
}

0

Jak powiedzieli inni, nie można zrezygnować z używania post / redirect / get. Ale jednocześnie dość łatwo jest robić to, co chcesz, po stronie serwera.

Na swojej stronie POST po prostu zatwierdzasz dane wejściowe użytkownika, ale nie wykonujesz na nich żadnych działań, zamiast tego kopiujesz je do tablicy SESSION. Następnie ponownie przekierowujesz z powrotem do głównej strony przesyłania. Twoja główna strona przesyłania zaczyna się od sprawdzenia, czy tablica SESSION, której używasz, istnieje, a jeśli tak, skopiuj ją do tablicy lokalnej i usuń jej ustawienie. Stamtąd możesz na nim działać.

W ten sposób wykonujesz całą swoją główną pracę tylko raz, osiągając to, co chcesz.


0

Szukałem rozwiązania, aby zapobiec ponownemu złożeniu później dużego projektu. Kod bardzo dobrze działa z $ _GET i $ _POST i nie mogę zmienić zachowania elementów formularza bez ryzyka nieprzewidzianych błędów. Oto mój kod:

<!-- language: lang-php -->
<?php

// Very top of your code:

// Start session:
session_start();

// If Post Form Data send and no File Upload
if ( empty( $_FILES ) && ! empty( $_POST ) ) {
    // Store Post Form Data in Session Variable
    $_SESSION["POST"] = $_POST;
    // Reload Page if there were no outputs
    if ( ! headers_sent() ) {
        // Build URL to reload with GET Parameters
        // Change https to http if your site has no ssl
        $location = "https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
        // Reload Page
        header( "location: " . $location, true, 303 );
        // Stop any further progress
        die();
    }
}

// Rebuilt POST Form Data from Session Variable
if ( isset( $_SESSION["POST"] ) ) {
    $_POST = $_SESSION["POST"];
    // Tell PHP that POST is sent
    $_SERVER['REQUEST_METHOD'] = 'POST';
}

// Your code:
?><html>
    <head>
        <title>GET/POST Resubmit</title>
    </head>
    <body>

    <h1>Forms:</h1>
    <h2>GET Form:</h2>
    <form action="index.php" method="get">
        <input type="text" id="text_get" value="test text get" name="text_get"/>
        <input type="submit" value="submit">
    </form>
    <h2>POST Form:</h2>
    <form action="index.php" method="post">
        <input type="text" id="text_post" value="test text post" name="text_post"/>
        <input type="submit" value="submit">
    </form>
    <h2>POST Form with GET action:</h2>
    <form action="index.php?text_get2=getwithpost" method="post">
        <input type="text" id="text_post2" value="test text get post" name="text_post2"/>
        <input type="submit" value="submit">
    </form>
    <h2>File Upload Form:</h2>
    <form action="index.php" method="post" enctype="multipart/form-data">
        <input type="file" id="file" name="file">
        <input type="submit" value="submit">
    </form>

    <h1>Results:</h1>
    <h2>GET Form Result:</h2>
    <p>text_get: <?php echo $_GET["text_get"]; ?></p>
    <h2>POST Form Result:</h2>
    <p>text_post: <?php echo $_POST["text_post"]; ?></p>
    <h2>POST Form with GET Result:</h2>
    <p>text_get2: <?php echo $_GET["text_get2"]; ?></p>
    <p>text_post2: <?php echo $_POST["text_post2"]; ?></p>
    <h2>File Upload:</h2>
    <p>file:
    <pre><?php if ( ! empty( $_FILES ) ) {
            echo print_r( $_FILES, true );
        } ?></pre>
    </p>
    <p></p>
    </body>
    </html><?php
// Very Bottom of your code:
// Kill Post Form Data Session Variable, so User can reload the Page without sending post data twice
unset( $_SESSION["POST"] );

Działa tylko w celu uniknięcia ponownego przesłania $ _POST, a nie $ _GET. Ale to jest zachowanie, którego potrzebuję. Problem z ponownym przesłaniem nie działa w przypadku przesyłania plików!


0

To, co działa dla mnie, to:

if ( !refreshed()) {
   //Your Submit Here
        if (isset( $_GET['refresh'])) {
            setcookie("refresh",$_GET['refresh'], time() + (86400 * 5), "/");
        }

    }    
}


function refreshed()
{
    if (isset($_GET['refresh'])) {
        $token = $_GET['refresh'];
        if (isset($_COOKIE['refresh'])) {
            if ($_COOKIE['refresh'] != $token) {
                return false;
            } else {
                return true;
            }
        } else {
            return false;
        }
    } else {
        return false;
    }
}  


function createToken($length) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

?>

I w swojej Formie

 <form  action="?refresh=<?php echo createToken(3)?>">



 </form>

0

Ten form.phpprzykład pokazuje, jak poprawnie używać PRG (kiedy formularz jest prawidłowy lub nie).

  • Przekierowuje na tę samą stronę tylko wtedy, gdy formularz jest prawidłowy i akcja została wykonana.
  • Przekierowanie chroni formularz przed ponownym przesłaniem podczas odświeżania strony.
  • Używa sesji, aby nie stracić komunikatów o sukcesie, które chcesz pokazać, gdy formularz jest prawidłowy.
  • Istnieją dwa przyciski do testowania: „Prześlij prawidłowe”, „Prześlij nieprawidłowe”. Wypróbuj oba, a następnie odśwież stronę.
<?php
session_start();

function doSelfRedirect()
{
  header('Location:'.$_SERVER['PHP_SELF']);
  exit;
}

function setFlashMessage($msg)
{
  $_SESSION['message'] = $msg;
}

function getFlashMessage()
{
  if (!empty($_SESSION['message'])) {
    $msg = $_SESSION['message'];
    unset($_SESSION['message']);
  } else {
    $msg = null;
  }

  return $msg;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  // Validation primitive example.
  if (empty($_POST['valid'])) {
    $formIsValid = false;
    setFlashMessage('Invalid form submit');
  } else {
    $formIsValid = true;
  }

  if ($formIsValid) {
    // Perform any actions here.
    // ...

    // Cool!
    setFlashMessage('Form is valid. Action performed.');

    // Prevent form resubmission.
    doSelfRedirect();
  }
}
?>
<h1>Hello form</h1>

<?php if ($msg = getFlashMessage()): ?>
  <div><?= $msg ?></div>
<?php endif; ?>

<form method="post">
  <input type="text" name="foo" value="bar"><br><br>
  <button type="submit" name="invalid" value="0">Invalid submit</button>
  <button type="submit" name="valid" value="1">Valid submit</button>
</form>

-2
if (($_SERVER['REQUEST_METHOD'] == 'POST') and (isset($_SESSION['uniq']))){
    if($everything_fine){
        unset($_SESSION['uniq']);
    }
}
else{
    $_SESSION['uniq'] = uniqid();
}

Dodaj wyjaśnienie do swojej odpowiedzi, tak aby inni mogli się z niej nauczyć - skąd się to $everything_finewzięło?
Nico Haase

-3

Dlaczego nie użyć tej $_POST['submit']zmiennej jako logicznej instrukcji, aby zapisać wszystko, co jest w formularzu. Zawsze możesz przekierować na tę samą stronę (w przypadku, gdyby się odświeżyły i gdy trafią go backw przeglądarce, zmienna przesyłania wiadomości nie będzie już ustawiana. Upewnij się tylko, że przycisk przesyłania ma a namei idof submit.


1
Zajrzyj na en.wikipedia.org/wiki/Post/Redirect/Get ! To jest właściwe podejście
267 stycznia
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.