Kontrola formulářových polí

Školení, která pořádám

Pokud chceme uživatele donutit vyplnit nějaké formulářové pole, musíme to kontrolovat na serveru, protože kontrola u klienta např. JavaScriptem není spolehlivá (uživatel může mít JavaScript vypnutý, navíc může náš formulář obejít i jinak). Kontrola u klienta je ale pohodlnější, protože data se nemusí posílat na server a zpátky jenom kvůli tomu, aby se zjistilo, že jsou špatně vyplněná. Nejlepší je tedy obě metody zkombinovat:

<?php
$povinne = array("jmeno" => "Jméno", "prijmeni" => "Příjmení");

function nevyplnene($povinne) {
    $nevyplnene = array();
    foreach ($povinne as $key => $val) {
        if (!$_POST[$key]) {
            $nevyplnene[] = $val;
        }
    }
    return $nevyplnene;
}

if (isset($_POST["sent"])) {
    $nevyplnene = nevyplnene($povinne);
    if (!$nevyplnene) {
        mysql_query("INSERT INTO uzivatele (jmeno, prijmeni, email) VALUES ('" . mysql_real_escape_string($_POST["jmeno"]) . "', '" . mysql_real_escape_string($_POST["prijmeni"]) . "', '" . mysql_real_escape_string($_POST["email"]) . "')");
        header("Location: ulozeno.php");
        exit;
    }
    echo "<p>Nevyplněné položky: " . implode(", ", $nevyplnene) . "</p>\n";
}
?>
<script type="text/javascript">
function checkFields(frm) {
	for (i=1; i < arguments.length; i++) {
		if (frm[arguments[i]].value == '') {
			frm[arguments[i]].focus();
			alert('Vyplňte všechny položky označené hvězdičkou.');
			return false;
		}
	}
	return true;
}
</script>

<form action="" method="post" onsubmit="return checkFields(this, '<?php echo implode("', '", array_keys($povinne)); ?>');">
<p>
<input type="hidden" name="sent" value="1" />
Jméno: <input name="jmeno" value="<?php echo htmlspecialchars($_POST["jmeno"]); ?>" maxlength="50" /> *<br />
Příjmení: <input name="prijmeni" value="<?php echo htmlspecialchars($_POST["prijmeni"]); ?>" maxlength="50" /> *<br />
E-mail: <input name="email" value="<?php echo htmlspecialchars($_POST["email"]); ?>" maxlength="50" /><br />
<input type="submit" value="Odeslat" />
</p>
</form>

Funkce checkFields i nevyplnene je samozřejmě vhodné umístit do samostatných souborů. U HTML kódu si všimněte několika věcí:

Přijďte si o tomto tématu popovídat na školení JavaScript a AJAX.

Jakub Vrána, Řešení problému, 27.7.2005, diskuse: 21 (nové: 0)

Diskuse

ikona dgx:

S tím neodesláním hodnoty tlačítka submit při stlačení Enteru jsi mi vyfoukl téměř dokončený článek ;) Tak to alespoň zdůrazním tímto komentářem...

Mise:

To neodeslani hodnoty pri enteru by me zajimalo. Ve standardu jsem o tom kdysi nasel, ze se nema posilat pokud formular obsahuje jen jeden input (hiddeny se nepocitaj), coz si IE vyklada jako: "na selectech nezalezi" a Mozilla jako "select je stejne dobrej jako input". Na jinou situaci, kdy by se tlacitko po enteru neposlalo sem nenarazil.

ikona Jakub Vrána OpenID:

Podrobný článek na toto téma: http://ppewww.ph.gla.ac.uk/~flavell/www/formquestion.html

Zdeněk Merta:

Uff - tak o neodeslani tlacitka Enterem jsem ani nevedel.

Petr:

A v kterych prohlizecich se teda to name submitu enterem neodesila?

ikona Jakub Vrána OpenID:

Omlouvám se za FUD, vyzkoušel jsem to ve Firefoxu 1, Opeře 8 a IE 6 a podařilo se mi to reprodukovat v IE 6 za situace, kdy formulář obsahoval jediný <input type="text">, jinde ne. Starší prohlížeče se ale mohou chovat jinak.

Petr Weida:

Doplnil bych relevantní odkaz:

http://www.izsak.net/weblog/109/msie-a-element-button-riesenie

Michal:

Nemela by hlavicka te javascriptove funkce byt spis function check_fields(frm, arguments) ? Ale mozna je to jenom nejaka magie, ktere nerozumim...

ikona Jakub Vrána OpenID:

Je to opravdu magie. Pole arguments bsahuje všechny parametry předané funkci. Pokud by funkce byla ve tvaru check_fields(frm, args), musela by se volat jako check_fields(this, ['a', 'b']).

ondra:

Zdravim,
omlouvam se, ze reaguji na stary clanek, ale pokud uzivatel nevyplni nejaka pole, my ho na dalsi strance upozornime, nabidneme tlacitko zpet, a v hiddenech posleme udaje, aby se mu znovu zobrazily. Je mi to jasne u input=text, ale pokud je to select, checkbox nebo radio, jak poslete hodnoty tak, aby se ve formulari zobrazily?

Popripade by me zajimalo jak se dela hezci zpusob, kde se po nevyplneni nekterych polozek stranka presmeruje na formular, kde jsou jiz vyplena pole znovu vyplena a seznam nevyplnenych se vypise.

Zajima me, ja se hodnoty poslou zpet, kdyz se to redirektuje, tzn uzivatel neklepne na tlacitko, ktere odesle hiddeny a v getu to posilat je nesmysl.

Dekuji za pripadnou radu.

ikona Jakub Vrána OpenID:

Tlačítko zpět je zbytečné. Vypsat zadané hodnoty jde jednoduše pomocí <input name="a" value="<?php echo htmlspecialchars($_POST["a"]); ?>">. <select> třeba takhle:
<select name="b">
<?php
foreach ($options as $key => $val) {
    echo "<option value='$key'" . ($key == $_POST["b"] ? " selected='selected'" : "") . ">$val</option>\n";
}
?>
</select>

ondra:

diky za ten select.

Asi jsem to prvni nepochopil;) pokud formular zpracovava "jina stranka", tak myslite, ze ty zadane hodnoty se vypisou na te jine strance? Jakoby druhy formular s action="jina stranka"?

Myslel jsem presmerovani na puvodni formular, pokud nejaka hodnota chybi a poslat zpet ty hodnoty co byly zadany me nenapada jinak nez pomoci hiddenu.

Pokud mam dlouhe vedeni a jsem mimo misu, tak se omlouvam.

ikona Jakub Vrána OpenID:

Všimni si, že formulář se odesílá na stejnou stránku, kde se zobrazuje. Pokud je vše v pořádku, proběhne přesměrování hlavičkou Location, jinak se formulář zobrazí znovu.

ondra:

jo tak, pardon;) ja to vztahoval na svuj formular, u vas jsem koukal jen na ten pekny javascript;)

diky

deny:

kdyz dam kontrolu formulare v jine php strance, tak se mi stava,ze po hlasce pr.vyplnte vsechny pole, to co jiz bylo vyplneno zmizi, takze to cloveka spis nastve nez aby to podruhe vyplnoval znova. dik za radu. Taky mam problem s odesilanim fotografie, nejdriv se mi odesilala na maila jen cesta k obrazku,ale vubec nevim jak s tim hnout..

ikona Jakub Vrána OpenID:

Soubory se dají posílat např. pomocí http://pear.php.net/package/Mail_Mime

Jirka:

Chtěl bych se zeptat jestli atribut onsubmit bude fungovat i v případě že je tlačítko odeslat formou <input type=image>.
Děkuji za případnou odpověď.

ikona Jakub Vrána OpenID:

Ano.

Martin Žák:

Prosím, jak to mám upravit, aby mi skript fungoval i pro inputy typu radio? Mám anketu (25 otázek) a u každé je 6 radio inputů (likertovská škála). Skript tak, jak je, mi odešle formulář, aniž bych sáhl na jediné radio, a když jsem ho upravil a místo if (frm[arguments[i]].value == '') napsal if (frm[arguments[i]].value == null), tak mi zase formulář nechce odeslat nikdy.
Jak z toho ven?

jirka:

Ahoj. chci docílit toho, že když nemam nějaké pole vyplněné, tak aby se mi vyplněné údaje nezapsali do txt souboru.

<?php
if($send="submited"){
$f =fopen("zkouska1.txt", "a");
$text=implode("#" ,$_POST)."\n";
fwrite($f ,$text,strlen($text));
fclose($f);
}
else{
if (empty(
$jmeno)){
        echo "<strong>Musíte zadat vaše jméno.</strong><br />";
        $predmet_error=1;
        }

        if (empty($email)){
        echo "<strong>Musíte zadat existující e-mail.</strong><br />";
        $email_error=1;
        }else{

        if ((@!strpos ($email,"@")) || (@!strpos ($email,"."))){
        echo "<strong>Musíte zadat existující e-mail.</strong><br />";
        $email_error=1;
        }}

        if (empty($narozeni)){
        echo "<strong>Musíte zadat sve datum narozeni.</strong><br />";
        $narozeni_error=1;
        }

        if (empty($mesto)){
        echo "<strong>Musíte zadat mesto.</strong><br />";
        $mesto_error=1;
        }
}
?>

leorond:

Dobrý večer,
již více než 5 let pracuji s MS SQL databázemi, nyní jsem nucen pracovat s My SQL a ten rozdíl je znatelný.

No chci reagovat na tento článek, zdá se mi nesmyslné při menším projektu po vyplnění formuláře odeslat na druhou stránku kde se vypíše hláška. Uživatele to jen odradí, zkusil bych třeba něco takového:

<?php
$povinne
= array("jmeno" => "Jméno", "prijmeni" => "Příjmení", "email" => "Email", "telefon" => "Telefon", "zprava" => "Zpráva");

function
nevyplnene($povinne) {
   
$nevyplnene = array();
    foreach (
$povinne as $key => $val) {
        if (!
$_POST[$key]) {
           
$nevyplnene[] = $val;
        }
    }
    return
$nevyplnene;
}

if (isset(
$_POST["sent"])) {
   
$nevyplnene = nevyplnene($povinne);
    if (!
$nevyplnene) {
       
mysql_query("INSERT INTO test (jmeno, prijmeni, email, telefon, zprava) VALUES
        ('"
. mysql_real_escape_string($_POST["jmeno"])
        .
"', '" . mysql_real_escape_string($_POST["prijmeni"])
        .
"', '" . mysql_real_escape_string($_POST["email"])
        .
"', '" . mysql_real_escape_string($_POST["telefon"])
        .
"', '" . mysql_real_escape_string($_POST["zprava"])
        .
"')");
        echo
"Váš dotaz byl odeslán na mysql!";
    }
    else
    {
    echo
"<p>Nevyplněné položky: " . implode(", ", $nevyplnene) . "</p>\n";
    }
}
?>
<script type="text/javascript">
function checkFields(frm) {
    for (i=1; i < arguments.length; i++) {
        if (frm[arguments[i]].value == '') {
            frm[arguments[i]].focus();
            alert('Vyplňte všechny položky označené hvězdičkou.');
            return false;
        }
    }
    return true;
}
</script>

<form action="" method="post" onsubmit="'<?php echo implode("', '", array_keys($povinne)); ?>');">
<p>
<input type="hidden" name="sent" value="1" />
Jméno: <input name="jmeno" value="<?php echo htmlspecialchars($_POST["jmeno"]); ?>" maxlength="10" /> *<br />
Příjmení: <input name="prijmeni" value="<?php echo htmlspecialchars($_POST["prijmeni"]); ?>" maxlength="20" /> *<br />
E-mail: <input name="email" value="<?php echo htmlspecialchars($_POST["email"]); ?>" maxlength="50" /> *<br />
Telefon: <input name="telefon" value="<?php echo htmlspecialchars($_POST["telefon"]); ?>" maxlength="9" /> *<br />
Zpráva: <textarea  cols="28" rows="10" name="zprava" value="<?php echo htmlspecialchars($_POST["zprava"]); ?>" maxlength="1500" /></textarea> *<br />
<input type="submit" value="Odeslat" />
</p>
</form>

Zůstane mi zde vše zapsané, tedy až na odesílanou zprávu a přitom nikam uživatele nesměřuji, dávám mu jasnou odpověd na jeho otázku "Co je špatně?" a zároveň by bylo dobré zahrnout do scriptu kontrolu emailu "správný formát", také určitě ověření zda není již stejný zápis v DB aby se mi netvořil duplikát, nezapomenout třeba na spamovou otázku.

Pokud už chcete nějaký formulář na web dávat, ať obsahuje vše důležité a uživatel ať má všechny podstatné odpovědi na své otázky.

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.