Internet Info, s.r.o. Lupa Měšec Podnikatel Root Zdroják DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Nette Framework: Neprůstřelné formuláře

Formuláře změnily Internet, z akademické sítě učinily komerční prostředí. Najednou bylo možno odesílat objednávky na e-shopech nebo poptávky přes kontaktní formuláře. Jak vypadá tvorba formuláře v Nette Framework?

Tweetni to Twitter Jaggni to! Jagg Del.icio.us Delicious

Ještě než si napíšeme v Nette Framework první formulář, je potřeba říci, že formuláře jsou sice dobří sluhové, ale zlí páni. Jestliže jsem se o sessions zmiňoval jako o potenciálním zdroji největších bezpečnostních děr, o formulářích musím prohlásit to stejné. Opět ale platí, že Nette Framework klade velký důraz na bezpečnost aplikací, a proto vynakládá značné úsilí i pro zabezpečení formulářů. Dělá to zcela transparentně, nevyžaduje nic manuálně nastavovat a troufám si říci, že v této oblasti má velký náskok před ostatními frameworky.

Nette Framework ochrání vaše aplikace před útokem Cross-Site Request Forgery (CSRF), odfiltruje ze vstupů kontrolní znaky, ujistí se, že všechny textové vstupy představují validní UTF-8 řetězce, že položky označené v select boxech skutečně patří mezi nabízené, automaticky ořeže mezery na jednořádkovém textovém políčku atd.

Registrační formulář

Pojďme si vytvořit registrační formulář (kód si můžete stáhnout):

require 'Nette\loader.php';

// pokud používáte verzi pro PHP 5.3, odkomentujte následující řádek:
// use Nette\Forms\Form, Nette\Debug;

Debug::enable();

$countries = array(
    'Evropa' => array(
        'CZ' => 'Česká republika',
        'FR' => 'Francie',
        'DE' => 'Německo',
        'SK' => 'Slovensko',
        'GB' => 'Velká Británie',
    ),
    'AU' => 'Austrálie',
    'CA' => 'Kanada',
    '?'  => 'jiná',
);

$sex = array(
    'm' => 'muž',
    'f' => 'žena',
);

$form = new Form;
$form->addText('name', 'Jméno:');
$form->addText('age', 'Věk:');
$form->addRadioList('gender', 'Pohlaví:', $sex);
$form->addText('email', 'E-mail:');
$form->addCheckbox('promo', 'zasílejte mi reklamu');
$form->addSelect('country', 'Země:', $countries);
$form->addPassword('password', 'Heslo:');
$form->addPassword('password2', 'Heslo pro kontrolu:');
$form->addSubmit('register', 'Registrovat');

echo $form; 

Vykreslí se vám následující formulář:

Nette formulář

Upozornění: skripty musí být uloženy v UTF-8.

Samotný kód je dostatečně samovysvětlující a ve spojení s obrázkem asi nepotřebuje dalšího komentáře. Snad jen dodám, že u každé metody addXyz() představuje první parametr interní identifikátor, tedy jakési ID prvku. K jednotlivým prvkům lze poté přistupovat pomocí hranatých závorek, podobně jako k prvkům pole. Takže třeba $form['name'] je objektem třídy Nette\Forms\TextInput a představuje první položku formuláře.

Vykreslený formulář splňuje základní pravidlo přístupnosti – všechny popisky jsou označeny jako <label> a provázané s formulářovým prvkem. Můžete tedy myší kliknout na popisku a kurzor se přesune do prvku. Zároveň jsou ošetřeny chyby prohlížečů (tedy vlastně prohlížeče Internet Explorer) týkající se select boxu: kliknutí na popisku nebo otočení kolečkem myši nesmaže výběr. HTML podoba formuláře se dá kompletně změnit, jak si ukážeme v dalším pokračování.

Už v prvním díle seriálu jsme si říkali o životním cyklu formuláře, který začíná zrozením (tedy definicí) formuláře, pokračuje testem na to, zda byl odeslán (is submitted?) a jestli je validní (is valid?), v případě kladných odpovědí vstupní data zpracujeme, v opačném případě jej zobrazíme uživateli.

Za definici formuláře tedy vložte kód:

// jestliže byl formulář odeslán
if ($form->isSubmitted()) {
    // a jestliže jsou všechny položky vyplněny správně
    if ($form->isValid()) {
        echo '<h1>Formulář byl odeslán</h1>';

        $values = $form->getValues();
        Debug::dump($values);
        exit;
    }

} else {
    // a jestliže nebyl odeslán, nastavíme výchozí hodnoty
    $form->setDefaults(array(
        'promo' => TRUE,
    ));} 

Dotazem $form->isSubmitted() lze detekovat první zobrazení formuláře – pokud vrací false, formulář nebyl odeslán a je tedy uživateli předložen poprvé. V takovém případě mu nastavíme výchozí hodnoty metodou setDefaults. Výchozí hodnoty tvoří pole, kde jednotlivé klíče představují výše zmíněné ID prvků.

Pokud naopak formulář odeslán byl, je potřeba ještě metodou isValid() ověřit, zda byl vyplněn korektně. Existují ale případy, kdy můžeme jednat i bez ověření validace – například pokud formulář obsahuje tlačítko Cancel nebo Zpět a toto bylo stisknuto. Zda byl vícetlačítkový formulář odeslán konkrétním tlačítkem, zjistíme dotazem např.  if ($form['register']->isSubmittedBy()).

Aby bylo ověřování validace smysluplné, musíme formuláři nastavit nějaká validační pravidla. K tomu složí metoda addRule(), kde první argument říká, jakou vlastnost chceme ověřovat a druhý argument je text chybové hlášky. Asi nejčastěji se budete setkávat s pravidlem Form::FILLED, které požaduje, aby prvek byl vyplněn (nebo měl zvolenou hodnotu v případě select boxu či radio listu):

$form->addText('name', 'Jméno:')
    ->addRule(Form::FILLED, 'Zadejte jméno'); 

Zajímavostí je, že Nette Framework automaticky detekuje, že prvek je povinný, a proto mu nastaví CSS třídu required. Pokud stylem .required { color: darkred } změníme prvkům barvu, hned se nám vykreslí takto:

Nette formulář

Podobně budeme vyžadovat i povinné vyplnění věku, navíc přidáme kontrolu, zda jde o číslo ( Form::INTEGER) a zda je v povoleném rozsahu ( Form::RANGE). Zde využijeme třetí parametr metody addRule, kterým předáme validátoru informaci o rozsahu:

$form->addText('age', 'Věk:')
    ->addRule(Form::FILLED, 'Zadejte věk')
    ->addRule(Form::INTEGER, 'Věk musí být číslo')
    ->addRule(Form::RANGE, 'Věk musí být v rozmezí od 5 do 120 let', array(5, 120)); 

Zde vzniká prostor pro drobný refactoring. V chybové hlášce a třetím parametru se duplikuje číselná informace, což není nikdy dobře. Navíc v dalším pokračování se dostaneme k překládání formulářů a pokud by se hláška obsahující čísla přeložila do více jazyků, ztížila by se případná úprava intervalu. Z toho důvodu je možné použít zástupné znaky v tomto formátu:

...
    ->addRule(Form::RANGE, 'Věk musí být v rozmezí od %d do %d let', array(5, 120)); 

Dalším políčkem, které budeme chtít validovat, je e-mailová adresa. Její platnost ověřuje pravidlo  Form::EMAIL.

$form->addText('email', 'E-mail:')
    ->addRule(Form::EMAIL, 'E-mailová adresa není platná'); 

Pravidlo Form::FILLED přidáme prvkům country, password a password2. Heslo budeme ještě kontrolovat na minimální délku ( Form::MIN_LENGTH), opět s využitím zástupného znaku:

$form->addPassword('password', 'Heslo:')
    ->addRule(Form::FILLED, 'Zvolte si heslo')
    ->addRule(Form::MIN_LENGTH, 'Zadané heslo je příliš krátké, zvolte si heslo alespoň o %d znacích', 3); 

A druhé heslo zkontroluje rovnost (tj. Form::EQUAL) s heslem prvním (všimněte si odvolávky na první heslo):

$form->addPassword('password2', 'Heslo pro kontrolu:')
    ->addRule(Form::FILLED, 'Zadejte heslo ještě jednou pro kontrolu')
    ->addRule(Form::EQUAL, 'Zadané hesla se neshodují', $form['password']); 

Hotový příklad si opět můžete stáhnout a vyzkoušet. Uvidíte, že kromě validace na straně serveru se automaticky dostala ke slovu i validace na straně prohlížeče (tj. javascriptová validace). Všimněte si, že po chybové zprávě se vždy kurzor umístí do příslušného políčka.

Uživatel se dostal do kolečka na křečka: dokud formulář nevyplní správně, je mu předkládán stále dokola s výpisem chyb.

Tímto ovšem validační možnosti zdaleka nekončí. Předností Nette Framework jsou tzv. validační podmínky, pomocí nichž uděláme políčko s e-mailem nepovinné. Ty najdete v příštím pokračování.


Autor článku je vývojář na volné noze, specializuje se na návrh a programování moderních webových aplikací. Vyvíjí open-source knihovny Texy, dibi a Nette Framework a pravidelně pořádá školení pro tvůrce webových aplikací, které od podzimu 2009 nabídne kurz vývoje AJAXových aplikací.

David Grudl

David Grudl

David Grudl je autorem PHP knihoven Nette Framework, databázové vrstvy dibi a formátovače HTML kódu Texy!.

Školení Google+ pro firmy

DW - Školení PPC
  • Jak využít Google+ pro firemní komunikaci a marketing.
  • Čím se liší Google+ od Twitteru a Facebooku z pohledu firemního využití.
  • Jak využít Google+ v souladu s pravidly užívání.
  • Založení Google+ Page (Stránky) krok po kroku, včetně praktických tipů.

Detailní informace o školení Google+ »

Přehled názorů

Validace dle regexp
Kajman 2. 6. 2009 09:10
Nový
└ 
Re: Validace dle regexp
Michal Krause 2. 6. 2009 11:03
Nový
validace skupin
Aichi 2. 6. 2009 17:23
Nový
Po sté to samé?
Mastodont 2. 6. 2009 17:58
Nový
├ 
Re: Po sté to samé?
David Grudl 2. 6. 2009 23:46
Nový
├ 
Re: Po sté to samé?
Daniel Tlach 3. 6. 2009 08:49
Nový
│
└ 
Re: Re: Po sté to samé?
Mastodont 3. 6. 2009 23:07
Nový
│
 
└ 
Re: Re: Re: Po sté to samé?
David Grudl 4. 6. 2009 01:39
Nový
│
 
 
├ 
Re: Re: Re: Re: Po sté to samé?
David Grudl 4. 6. 2009 01:40
Nový
│
 
 
│
└ 
Re: Re: Re: Re: Re: Po sté to samé?
Martin Hassman 4. 6. 2009 05:32
Nový
│
 
 
└ 
Re: Re: Re: Re: Po sté to samé?
Mastodont 4. 6. 2009 07:58
Nový
│
 
 
 
└ 
Re: Re: Re: Re: Re: Po sté to samé?
David Grudl 4. 6. 2009 10:25
Nový
└ 
Re: Po sté to samé?
Roman Pištěk 3. 6. 2009 15:05
Nový
 
└ 
Re: Re: Po sté to samé?
Mastodont 4. 6. 2009 08:04
Nový
newbie
cckar 4. 6. 2009 09:01
Nový
└ 
Re: newbie
David Grudl 4. 6. 2009 12:35
Nový
Re: Nette Framework: Neprůstřelné formuláře
Langi 5. 6. 2009 02:06
Nový
└ 
Re: Re: Nette Framework: Neprůstřelné formuláře
Langi 5. 6. 2009 02:17
Nový
 
└ 
Re: Re: Re: Nette Framework: Neprůstřelné formuláře
Vít Šesták 5. 6. 2009 10:40
Nový
 
 
├ 
Re: Re: Re: Re: Nette Framework: Neprůstřelné formuláře
Langi 5. 6. 2009 11:24
Nový
 
 
└ 
Re: Validace e-mailu
Jakub Vrána 2. 7. 2009 12:18
Nový
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem