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:

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...
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.
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 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í: 13704x