Autor Zpráva
tatyalien
Profil
Dobrý den,
do titulku se mě nevešlo přesné změní... moje otázka spíš správně zní:
Jak se má správně navrhnout stránka na vkládání záznamů, aby bylo zamezení následujícímu:

Když vložím data do DB, přesměruji po "insertu" uživatele na jinou adresu přez header - to již umím a rozchodil jsem to ve vkládnu díky AM_, ale pokud dá uživatel v prohlížeči krok zpět, tak aby bylo zamezeno vložení znovu stejných dat (u diskuzí není třeba možné nastavit unikátní sloupec, který zadává uživatel, ale je nastaven na id, které si db dělá automaticky). Pokud tedy dá uživatel krok zpět, má "vyplněný" formulář a pokud klikne znova na tlačítko odeslat, vloží se korektně znovu ta samá data...

Nevím jestli mám na začátku formuláře si třeba vygenerovat někam (proměná, sesion,..) unikátní řetězec, číslo cokoliv a to uložit do DB s insertem a pak porovnávat, zda tam tento řetězec není, ale přijde mě to asi jako padlé na hlavu :-D raději bych se dozvěděl jak to řeší ostatní co vědí jak se co dělá ;)

Nebo jestli mě doporučíte aspoň nějaké čtivo... zatím používám hlavne Knihu od W. Jason Gilmore Velká Kniha PHP & MySQL 5 + internet a další knihy...
Taps
Profil
tatyalien:
tady máš určité typy http://www.mazlo.org/blog/clanek/83-Komentare-Jak-zabranit-opakovanemu-zapisu-do-databaze-plus-bonus-navic
tatyalien
Profil
Taps:
No tohle již defakto mám (tohle odstraňuje možnost F5ky), mě spíš šlo o to, že když pak uživatel klikne v prohlížeči nahoře na šipku "zpět" tak se dostane znovu na fomulář, má opět vyplněný formulář tak jak byl a jakmile klikne na odeslat tak se znovu vytvoří stejný záznam.
Taps
Profil
tatyalien:
pokud používáš header tak ten by ti měl smazat data která jsou obsaženy v poli GET nebo POST a v případě že klikneš v prohlížeči na šipku zpět tak by se ti měly zobrazit jen prázdné políčka
tatyalien
Profil
Taps:
Tak v tom případě nevím kde je zakopanej pes :-( Protože pokud odešelu data, přesmeruji se zpět na skript tak mám hodnoty formuláře vymazáno - ok. Ale pokud kliknu pak ve Firefoxu na tlačítko "přejít o jednu stránku zpět" tak se mě načte formulář s hodnotama, které tam byly a nic mě nebrání je znovu odeslat ;)

Struktura stránek je viz minulé vlákno.
DJ Miky
Profil
To bude vyplňovat Firefox automaticky, napadá mě snad jen kontrolovat poslední vložený záznam a pokud je stejný jako ten, co se má přidat, tak prostě vypsat chybovou hlášku.
tatyalien
Profil
DJ Miky:
No zkoušel jsem to i v opeře a i v ie (nerad, ale přece)... a dělaj to všechny prohlížeče :-D
Takže asi vyloženě budu doopravdy muset pak porovnávat data zda tam tytéž nejsou :-(
Taps
Profil
tatyalien:
zkus sem vložit kod formuláře + kod který ji zajištuje ukládání do databáze.
tatyalien
Profil
index
<?php
session_start();
require "./include/funkce_all.php";
$stranka = isset($_GET['clanek']) ? preg_replace('/[^a-z0-9_\\-]/i', '', $_GET['clanek']) : 'default';
// načtení části skriptu, pokud existuje
if (file_exists("scripts/$stranka.php")) {
    //sem muzes nacpat skript ktery neco provede a pak se v pripade potreby presmeruje jinam (aplikacni cast)
    require "scripts/$stranka.php";
}
?>
<head>
<title>
    titulek...
</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<style type="text/css">
styly...
</style>
	<div id="obal">
  		<div id="zahlavi">
			<img src="images/grafika_zahlavi.gif" alt="logo" width="377" height="41" />
		</div>
		<div id="navigace">
			<?php require "content/navigace.php"; ?>
		</div>
		<div id="obal_obsahu">
			<div id="obsah_vnitrni">
				<?php require "content/$stranka.php"; // sem nacpes zobrazovaci cast stranky ?>
			</div>
		</div>
		<div id="zapati">zápatí...</div>
	</div>
</body>
</html>


scripts/cosi.php - kontrola + vkládání do DB
$chyba = '';
if (!empty($_POST["btn_odeslano"])) {
    if ($_POST["txt_test"] != "") {
        $HodnotyVlozit = array();
        $HodnotyVlozit["pokus"] = "'".saveDB($_POST["txt_test"])."'";        
        $HodnotaProChygu = saveDB($_POST["txt_test"]); 
        if(!InsertTabulkyMysql("abc",$HodnotyVlozit,$HodnotaProChygu)) {
			$chyba = "Něpodařilo se vložit reklamujícího do DB.<br>";
		} else {
		// zatím odkazuji na stejnou stránku, jen pro tento příklad to je sem zpět.
            header("location:index.php?clanek=cosi");
            exit;
        }
    } else {
        $chyba = 'Nic neni zadano';
    }
}


content/cosi.php - formulář
<p class="error"><?php echo $chyba; ?></p>
<form action='' method='post'>
<fieldset>
<legend>Testovací....</legend>
<input type="text" name="txt_test" /><br />
<input type='submit' name='btn_odeslano' value='Odeslat'>
</fieldset>
</form>


Funkce InsertTabulkyMysql
function InsertTabulkyMysql($tabulka, array $HodnotyVlozit, $KatalogNaChybu) {
    // vytvoření dotazu, implode spojí hodnoty dle rozdělovače
    $query = "INSERT INTO $tabulka (" . implode(", ", array_keys($HodnotyVlozit)) .
        ") VALUES (" . implode(", ", $HodnotyVlozit) . ")";
    $result = mysql_query($query);
    // odeslání dotazu a zjištění, zda se příkaz provedl, pokud ne, vypíšu chybovou hlášku
    if (!$result) {
        echo "Vložení \"$KatalogNaChybu\" nelze vložit (INSERT příkaz).<br>\r\n";
        return false;
    } else {
    	return true;
    };
}


funkce saveDB
function saveDB($value){
   return mysql_real_escape_string(trim($value));
} 



Jen se předem omlouvám, čt-pátek (4-5.2.2010) budu v Norimberku pracovně, tak nevím jestli nějak budu reagovat, v sobotu kdyžtak budu dál spolupracovat, tak se nelekejte, že nebudu delší dobu reagovat
Mastodont
Profil
tatyalien:
Spolehlivý způsob, jak zabránit opakovanému zadání dat, tvoří příznak pro odeslaný formulář uložený do session - po uložení formuláře ho smažeš a pokud formulář dorazí znovu, příznak chybí a obsah formuláře zahodíš.
tatyalien
Profil
Mastodont:
Takže při prvotním zobrazení stránky vytvořím sessionu (například při kontrole, že se ještě nic neodeslalo). Po uložení dat jednoduše unset sessionu, přesměrovat. Pokud se pak vrátím pomocí šipky zpět, budu mít sice data předvyplněný, ale uložit to uživatel nebude moct, protože v podmíce při ukládání session nebude existovat.. to by myslím šlo ;). Prubnu to ale nejdřív v sobotu, dnes už to balím, zejtra vstávám ve 4h :-(
tatyalien
Profil
tak jsem asi natvrdlej, ale nějak nevím kam to nacpat, pokud to hodím do skryptu:
if (!$_POST) {
    $_SESSION["odeslano_test"] = "ne";
    $chyba = "Nastavil jsem session na ne.";
}

if (!empty($_POST["btn_odeslano"])) {
    if ($_POST["txt_test"] != "") {
        if ($_SESSION["odeslano_test"] == "ne") {
            $HodnotyVlozit = array();
            $HodnotyVlozit["pokus"] = "'".saveDB($_POST["txt_test"])."'";        
            $HodnotaProChygu = saveDB($_POST["txt_test"]); 
            if(!InsertTabulkyMysql("abc",$HodnotyVlozit,$HodnotaProChygu)) {
    			$chyba = "Něpodařilo se vložit reklamujícího do DB.<br>";
    		} else {
                unset($_SESSION["odeslano_test"]);
                header("location:index.php?clanek=cosi");
                exit;
            }
        } else {
            $chyba = "Neexistuje session odeslano.";
        }
    } else {
        $chyba = 'Nic neni zadano';
    }
}


tak se mě pak vždy pomocí šipky zpět session vytvoří, takže to nemá správný vliv, pokud to hodím do indexu, že poku neexistuje session, že ji vytvoří, tak to též nemá pak na to vliv, protože když se přesměruji po vložení dat do DB zpět na stejný skript, neexistuje session, tak jí znovu vytvoří.
tatyalien
Profil
Tak jsem to trochu upravil na funkční model, kde jakmile odešlu data, přesměruji se zpět na stránku. Kde se zobrazí tlačítko s nápisem "Zobrazit formulář" pokud na něj uživatel klikne zobrazí se komplet formulář a může uživatel zase zadávat data. Pokud uživatel klikne na tlačítko zpět v prohlížeči zobrazí se mu sice opět vyplněný formulář (to co se snažím zamezit), pokud nyní klikne znovu na tlačítko, zobrazí se hláška, že je již stejný záznam vložet + tlačítko na reset. Sice pokud nyní klikne na tlačítko, tak data co jsou vyplněná zmizej, ale to mě zase tak moc netrápí...

Tak jsem si to upravil aspoň takhle:

script
$chyba = '';
$zobrazit = true;
if (!empty($_POST["btn_odeslano"])) {
    if ($_POST["txt_test"] != "") {
        if ($_SESSION["odeslano_test"] == "ne") {
            $HodnotyVlozit = array();
            $HodnotyVlozit["pokus"] = "'".saveDB($_POST["txt_test"])."'";        
            $HodnotaProChygu = saveDB($_POST["txt_test"]); 
            if(!InsertTabulkyMysql("abc",$HodnotyVlozit,$HodnotaProChygu)) {
    			$chyba = "Něpodařilo se vložit reklamujícího do DB.<br>";
    		} else {
                $_SESSION["odeslano_test"] = "ano";
                header("location:index.php?clanek=cosi");
                exit;
            }
        } else {
            $chyba = "Pokoušíte se vložit 2x stejné data, prosím ověřte si zadané hodnoty.";
        }
    } else {
        $chyba = 'Nic neni zadano';
    }
}
if (!empty($_POST["btn_odeslano_reset"])) {
    if($_SESSION["odeslano_test"] == "ano"){
        $_SESSION["odeslano_test"] = "ne";
    }
}


a formulář:
<p class="error"><?php echo $chyba; ?></p>
<form action='' method='post'>
<fieldset>
<legend>Testovací....</legend>
<?php if($_SESSION["odeslano_test"] == "ne") { ?>
<input type="text" name="txt_test" value="<?php echo $_POST["txt_test"]; ?>"/><br />
<input type='submit' name='btn_odeslano' value='Odeslat'>
<?php } else { ?>
<input type='submit' name='btn_odeslano_reset' value='Zobrazit formulář na zadávání dat.'>
<?php } ?>
</fieldset>
</form>

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0