PHP, submit di un form e l’errore del passato

Diverse volte mi è capitato di trovare sviluppatori con il solito problema: “esiste un modulo web che compilato regolarmente e inviata la richiesta al server presenta il classico messaggio di salvataggio, confermando all’utente che tutto è andato a buon fine. Il problema mi si presenta quando premo il tasto “indietro” del browser!“.

Di solito una pagina del genere è costituita dai seguenti spezzoni di codice (esemplificativi):

   <form method="post" action="mypage.php">
      <fieldset>
         <legend>
            Modulo contatti
         <legend>
         <p>
            <label for="nome">Nome</label>
            <input type="text" name="nome" id="nome" value="" />
         </p>
         <p>
            <label for="cognome">Cogome</label>
            <input type="text" name="cognome" id="cognome" value="" />
         </p>
         <p>
            <input type="submit" value="Procedi" />
         </p>
      </fieldset>
   </form>

mentre la parte di codice PHP che tratta il contenuto del modulo ha un funzionamento simile a quello che segue:

<?php
   if(isset($_POST) && count($_POST) > 0 ){
      $result = salvaDatiDelModulo($_POST);
      if($result === true){
         echo("Dati salvati correttamente");
      }else{
         echo("Si è presentato un errore durante il salvataggio del modulo: $result");
      }
   }
?>

Provando a premere il tasto F5 della tastiera dopo aver cliccato il pulsante Procedi sul modulo, vedrete un messaggio molto familiare (visibile su molte pagine web) e che, in dipendenza del browser utilizzato, mostra un messaggio del tipo: “La pagina sta provando a inoltrare di nuovo le informazioni di un modulo, si vuole procedere?“.

La conseguenza di un Submit eccessivo  può variare in dipendenza della complessità dell’applicazione e della gestione degli invii di richieste duplicate che talvolta,  a causa di un click spasmodico del tasto di Submit, può generare un inserimento duplicato di record in una banca dati, o la rimozione di più file dalla stessa directory o altri problemi che dovrebbero rientrare in un contesto di “Gestione degli errori”.

Lo stesso problema si presenta se per esempio dopo il Submit, abbiamo fatto click su un link della pagina, rendendoci conto di non essere sulla pagina giusta premiamo il pulsante “indietro” del Browser. Succede che il browser ci avverte che “la pagina è scaduta, è necessario nuovamente inoltrare i dati del modulo al server, bla bla bla…“. Le conseguenze di un inoltro sono le medesime descritte nel paragrafo precedente: record duplicati, eliminazioni di troppo, doppio invio email di email ecc.

Come si può evitare questo prolbema? Non è troppo difficile, eppure spesso si evita di gestire questo problema per inesperienza o perchè si tralascia valutando che le probabilità che un utente faccia click sul pulsante “indietro” del browser siano bassissime… Non è sempre così, le probabilità potrebbero essere altissime e la gestione del problema potrebbe risparmiare tanti grattacapi successivi.

La soluzione consiste nell’elaborare la richiesta quindi in qualsiasi caso dirottare la pagina verso un’altra destinazione (o verso se stessa) senza trasferire i dati in post, fornendo alla pagina di destinazione un ulteriore parametro che dovrebbe servire a comunicare il messaggio di errore o di successo all’utilizzatore del nostro modulo web.

Un’implementazione grezza ma già abbastanza efficace è la seguente:

<?php

   if(isset($_POST) && count($_POST) > 0 ){
      $result = salvaDatiDelModulo($_POST);
      $uri = $_SERVER['REQUEST_URI'];
      $uri .= (strpos('?',$uri)!==false)?'&','?';
      $uri .= 'msg=' . $result;
      header("Location: $uri", true); // Dirotto verso il nuovo URI ricostruito e rimpiazzo la location attuale nella barra degli indirizzi.
   }
   if(isset($_GET['msg']){
      $result = $_GET['msg'];
      if($result == 0){
         echo("Dati salvati correttamente");
      }else{
         // Prevedere un'array con i vari codici di errore e la relativa decodifica in messaggio testuale
         $msg = $codiciErrore[$result];
         echo("Si è presentato un errore durante il salvataggio del modulo: $msg");
      }
   }
?>

Quanto sopra consentirà di navigare anche avanti e indietro nella storia del browser o premere infinite volte il tasto F5 della tastiera!

Non era poi così complicato?  ;-)


Commenti

Una risposta a “PHP, submit di un form e l’errore del passato”

  1. Io qualche volta ho redirezionato, se l’operazione andava a buon fine, alla stessa pagina di compilazione del form inserendo in GET un flag (tipo form.php?ok=true) che mi permetteva di visualizzare un messaggio di conferma!