http://www.mazlo.org - Osobní stránky Jiřího Zamazala  

Komentáře: Jak zabránit opakovanému zápisu do databáze? (+ bonus navíc)

Netýká se to jen komentářů, ale jakýkoliv dat z formulářů, které se zapisují do databáze. Škoda jen, že tento problém pořád pár (nejen) blogů vůbec neřeší. A o co tedy vlastně jde? Uživatel odešle nějaká data z formuláře a pak omylem (?) stiskne tlačítko F5 vyvolávající aktualizaci stránky a opakované odeslání dat. Vysledkem jsou například dva a více stejné komentáře pod článkem.

Řešení znám zatím jen tři:

Přeloadování stránky

Dejme tomu, že se se nacházíme na adrese example.com/clanek.php?id=56-priklad s článkem a formulářem na odeslání komentářů. Formulář bude začínat takto: <form action="" method="post">. Data z formuláře tedy odešleme na toto samý soubor clanek.php. Na začátku (!) tohoto souboru pomocí podmínky zjistíme, jestli uživatel odeslal data z formuláře. Pokud ne, zobrazí se článek. Pokud ano, ověříme je a zapíšeme do databáze. Po tomto procesu provedeme přesměrování na stejnou adresu, na které se nyní nacházíme: header("Location: clanek.php?id=$_GET['id']");. Bravo, nyní se nacházíme na naší původní adrese bez POST dat, takže uživatel může klikat F5 jak dlouho chce... :-D

Jenže nic není tak snadné, jak na první pohled vypadá. Před funkcí header() nesmí prohlížeč, kromě hlaviček, obdržet žádná data. Před voláním funkce header() nesmí prohlížeč obdržet ani jednu mezeru, natožpak html tag! Pozor také dávejte na použití jazykového konstruktu echo či includování souboru.

Toto je je návrh souboru clanek.php:

<?php
if($_POST["nazev_inputu"]) {
  if(overovani_post_dat()){
    $insert = MySQL_Query("INSERT into ...");
      if($insert){
        header("Location: clanek.php?id=$_GET['id']");
        exit;
      }
      else
        $error = "Komentář se nepodařil vložit!";
  }
  else
    $error = "POST data nevyhověly podmínce. Komentář nemohl být vložen!";
    
}
//Zobrazení článku
if($error)
  echo $error;
?>
//Formulář na komentáře
<form action="" method="post">
<input type="text" name="nazev_inputu" value="<?php if($POST["nazev_inputu"] echo POST["nazev_inputu"])?>" />

Jistě jste si všimli, že jsem ukázku decentně rozšířil. Hned za použitím funkce header() ukončíme script pomocí exit;. Podmínka if(overovani_post_dat()) ve skutečnosti předtavuje množinu několika vnořených podmínek, ve kterých uvěřujete data. Jedná se o správně vyplnění všech povinných údajů, kontrolu emailu či IP adresy uživatele, atd. Do proměnné error tedy můžete uložit uznámení uživateli.

Pokud se tedy nemohl provést insert do databáze, vypíše se uživateli dovod neúspěchu a do inputů ve formuláři se zobrazí text, který již vyplnil. Spláchnuli jsme dvě mouchy (včetně té bonusové) jednou ranou. :-D

Přesměrování mezi dvěma soubory

Druhé řešení je složitější a navíc přidělává starosti. Začneme formulářem: <form action="insert.php" method="post">. Data z formuláře se odešlou do souboru insert.php, který je následně zpracuje. Tak či onak, z tohoto souboru vede jen přesměrování na původní adresu, tedy example.com/clanek.php?id=56-priklad. Takže při odesílání dat musíme posílat další informaci - id článku. Navíc co dělat, když se v insert.php nepovede insert do databáze? Co teď? Musíme při přesměrování na článek dát vědět, že něco není v pořádku. A také musíme přenést již zadané údaje, aby je uživatel nemusel zadávat znova. Jak přenést tyto informace „nazpět”? Přes cookies? Ne, tudy cesta nevede. Možné řešení je parametr přes url, což není to pravé ořechové. Nebo použít sessions.

Vítěz

Vítěz je jasný. „Přeloadování” stránky pomocí přesměrování na tentýž soubor vítězí. A navíc jsme spláchli do záchoda dvě mouchy jedním stisknutím. Zabránili jsme opakovanému zápisu do databáze a při špatném vyplnění formuláře jsme uživateli předvyplnili data, které zadal při předchozím pokusu.

Toto řešení používám i já, protože lepší neznám. Dříve jsem používal odeslání dat na insert.php a následné přesměrování na článek, ale hooodně rychle jsem od toho upustil.

Kategorie: Web a vše kolem něj ≈ 30. 09. 2006 ≈ Počet zobrazení: 18616x

Komentáře

Napsat komentář





;) :-P :-) :D 8-) :-O :( :-X .-)

  • Povinné údaje jsou zvýrazněny tučným písmem!
  • Formátování textu:
  • Povolené typy odkazů (příklady):
    • www.mazlo.org, http://www.mazlo.org či jen http://mazlo.org
    • https://www.t-zones.cz
    • ftp.slackware.cz (není povoleno ftp://ftp....!)
    • Za odkazem dělejte vždy mezeru!
  • Enter znamená nový řádek
  • Po 45 znacích ve slově se vytvoří mezera (vyjma odkazů)
  • RSS export komentářů tohoto článku
error414 [1229] -- 01. 10. 2006 10:53:19
me se vte treti moznosti nelibi ze kdyz spatne vyplni data a predvyplnio se formular tak po stisku refrese se to pta jestli ma znovu odeslat data. Sice to do databaze nezapise ale i tak je to hodne neprijemne.
 
 
Mazlo [1230] -- 01. 10. 2006 12:58:30
Máš pravdu. Ale když uživatel třeba zapomene vyplnit nick a objeví se mu hláška a předvyplněný formulář, jistě nebude mačkat F5, ale doplní nick a odešle.
Webmaster | Kontakt | Reagovat
 
 
error414 [1232] -- 01. 10. 2006 19:29:11
ja to resim pres cookie, kdyz je to private zone tak pres session. Nerikam ze je to elagantnejsi nebo lepsi, ale uz to tak delam dlouho.
Peter Zádori [1235] -- 03. 10. 2006 19:52:04
Zaujímavý komentár hlavne pre tých, čo si robia blog so svojím RS.
peterzadori (zavinac) post.sk | www | IM: 348740071 | Reagovat
mr.stepka [1237] -- 05. 10. 2006 16:26:16
Zajímavá diskuse k řešení opakovaného zápisu je na webu forum.builder.cz/read.php?14,1770888
tondovo [1399] -- 02. 03. 2007 09:57:12
Jenom bych dodal, že by tam měla bejt absolutní adresa, i když prohlížeče přežijou i relativní

Header(\"Location: $_SERVER[SERVER_NAME]:$_SERVER[...\");
mahrew [1417] -- 10. 03. 2007 20:26:19
A co tlacitko zpet ?
mahrew [1418] -- 10. 03. 2007 20:27:53
promiň, lae na to si asi nemyslel co?
test [1468] -- 02. 05. 2007 17:19:40
Test :-)
d [1565] -- 30. 12. 2008 13:36:36
d
Pavel [1591] -- 30. 06. 2009 19:56:05
Díky moc moc mo =)

Navigace

Kategorie

RSSad.cz: Chyba číslo 407 - Nejde načíst cacheRSSad.cz: Chyba číslo 407 - Nejde načíst cache

© 2005 - 2006 Jiří Zamazal alias Mazlo | Web pohání MRSS 1.0 | XHTML 1.0 Strict | Valid CSS | RSS: články / komentáře |