Lekce 1 - Tvorba formulářového frameworku v PHP - Motivace
V dnešním tutoriálu začneme pracovat na minimalistické knihovně, která za nás vyřeší všechny starosti ohledně formulářů. Formuláře se ve webové aplikaci vyskytují velmi často a tvoří její značnou část. Uvidíte, že díky knihovně ve svých aplikacích ušetříte obrovské množství kódu a času. Protože nám její tvorba zabere hned několik dílů a bude se jednat o poměrně pokročilou věc, rozhodl jsem se celý dnešní díl věnovat motivaci, aby byla vidět její přidaná hodnota. Co se týče názvosloví, jedná se již spíše o menší framework než knihovnu, nicméně v seriálu budu tato označení zaměňovat.
Formuláře v čistém PHP
Ukažme si, co všechno musíme v čistém PHP napsat, abychom uložili několik políček z formuláře do databáze. Vše si budeme ukazovat na zjednodušeném formuláři pro objednání automobilu, který vypadá takto:
![Tvorba formulářů v PHP - Pokročilá obsluha formulářů v PHP](images/5/php/php_formularova_knihovna.png)
HTML kód
Jakmile tvoříme nějaký formulář, začínáme nejčastěji HTML kódem. Budeme chtít, aby formulář nějak vypadal a byl responzivní, proto musíme navíc použít nějaké divy a spany. Také budeme používat HTML 5 atributy pro klientské validace, které pro náš příklad maximálně zjednodušíme. Náš HTML kód bude vypadat takto:
<form method="POST" id="objednavka-auta" class="fancyform"> <div class="form-component"> <label for="jmeno">Jméno</label> <input name="jmeno" id="jmeno" required="required" type="text"/> <div class="clear"></div> </div> <div class="form-component"> <label for="email">E-mail</label> <input name="email" id="email" type="email" /> <div class="clear"></div> </div> <div class="form-component"> <label for="znacka_vozu">Značka</label> <select name="znacka_vozu" id="znacka_vozu" required="required"> <option value="skoda">Škoda</option> <option value="bmw">BMW</option> <option value="audi">Audi</option> </select> <div class="clear"></div> </div> <div class="form-component"> <label for="nahon">Náhon</label> <select name="nahon" id="nahon" required="required"> <option value="predni">Přední</option> <option value="zadni">Zadní</option> <option value="vse">Všechny</option> </select> <div class="clear"></div> </div> <div class="form-component"> <label for="zpusob_platby">Způsob platby</label> <div name="zpusob_platby" id="zpusob_platby" class="radio-horizontal"> <span> <input name="zpusob_platby" id="zpusob_platby1" value="prevodem" type="radio" checked="checked"/> <label for="zpusob-platby1">Převodem</label> </span> <span> <input name="zpusob_platby" id="zpusob_platby2" value="sekem" type="radio"/> <label for="zpusob_platby2">Šekem</label> </span> <span> <input name="zpusob_platby" id="zpusob_platby3" value="hotovost" type="radio"/> <label for="zpusob_platby3">V hotovosti</label> </span> </div> <div class="clear"></div> </div> <div class="form-component"> <label for="poznamka">Poznámka</label> <textarea name="poznamka" id="poznamka"></textarea> <div class="clear"></div> </div> <div class="form-component"> <label for="vybava">Výbava</label> <div name="vybava" id="vybava" class="radio-horizontal"> <span> <input type="checkbox" name="abs" value="1" id="vybavaabs"/> <label for="vybavaabs">ABS</label> </span> <span> <input type="checkbox" name="sterace" value="1" id="vybavasterace"/> <label for="vybavasterace">Stěrače</label> </span> <span><input type="checkbox" name="asr" value="1" id="vybavaasr"/> <label for="vybavaasr">ASR</label> </span> <span> <input type="checkbox" name="eps" value="1" id="vybavaeps"/> <label for="vybavaeps">EPS</label> </span> </div> <div class="clear"></div> </div> <div class="form-buttons"> <input name="objednat" id="objednat" value="Objednat" type="submit"/> </div> </form>
Kód má zatím 74 řádek a zobrazuje 7 políček, to opravdu není efektivní. A bude hůř.
Validace
Data musíme zvalidovat znovu i na serveru, protože se na klientskou validaci nemůžeme spolehnout, ta slouží opravdu jen pro klienty, aby viděli, co mají špatně. Abychom se vyhnuli uložení nesmyslných hodnot do databáze, provedeme alespoň jednoduchou serverovou validaci:
if (isset($_POST['jmeno']) && ($_POST['jmeno']) && (!isset($_POST['email']) || (preg_match('/^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/u', $_POST['email']))) && isset($_POST['znacka_vozu']) && ($_POST['znacka_vozu']) && isset($_POST['nahon']) && ($_POST['nahon']) && isset($_POST['zpusob_platby']) && isset($_POST['poznamka']) && isset($_POST['vybava']))
Jsme na 81 řádcích.
Uložení hodnot do databáze
Objednávku uložíme do databáze následovně:
Db::dotaz(' INSERT INTO `objednavka` (jmeno, email, znacka_vozu, nahon, zpusob_platby, poznamka, vybava) VALUES (?, ?, ?, ?, ?, ?, ?) ', $_POST['jmeno'], $_POST['email'], $_POST['znacka_vozu'], $_POST['nahon'], $_POST['zpusob_platby'], $_POST['poznamka'], $_POST['vybava']);
Celkem 86 řádků pro vložení sedmi políček do databáze.
Formulářová knihovna
Nyní si ukažme, jak by vypadalo zpracování identického formuláře pomocí naší knihovny.
Definice formuláře
Formulář vytvoříme jako instanci třídy Form
a přidáme do
něj jednotlivá pole:
$form = new Form('objednavka-auta'); $form->addTextBox('jmeno', 'Jméno', true); $form->addEmailBox('email', 'E-mail', false); $form->addComboBox('znacka_vozu', 'Značka', true) ->setValues(array( 'Škoda' => 'skoda', 'BMW' => 'bmw', 'Audi' => 'audi', )); $form->addComboBox('nahon', 'Náhon', true) ->setValues(array( 'Přední' => 'predni', 'Zadní' => 'zadni', 'Všechny' => 'vse', )); $form->addRadioGroup('zpusob_platby', 'Způsob platby', true) ->setValues(array( 'Převodem' => 'prevodem', 'Šekem' => 'sekem', 'V hotovosti' => 'hotovost', )); $form->addTextArea('poznamka', 'Poznámka', false); $form->addCheckList('vybava', 'Výbava') ->setValues(array( 'ABS' => 'abs', 'Stěrače' => 'sterace', 'ASR' => 'asr', 'EPS' => 'eps', )); $form->addButton('objednat', 'Objednat');
Zatím máme 29 řádek pro 7 polí, což je dobrý poměr. Řádky navíc jsou jen možnosti k výběru.
HTML kód
HTML kód se vygeneruje plně automaticky, stačí pouze zavolat metodu
render()
na instanci formuláře:
<?= $form->render() ?>
Validace
Serverové validace proběhnou plně automaticky při prvním pokusu o čtení hodnot z formuláře.
Uložení hodnot do databáze
Pokud formulářový framework použijeme spolu s místním databázovým frameworkem, bude uložení dat do databáze vypadat následovně:
Db::insert('objednavka', $form->getData());
Celková velikost kódu: 31 řádků oproti 86 řádkům bez použití frameworku. Přes 60% kódu jsme úplně vyhodili a nestalo se vůbec nic. Za zbylý čas bychom napsali ještě další 2 formuláře. Příklad byl opravdu velmi zjednodušený, v praxi by byly rozdíly na větších formulářích a složitějších validacích ještě markantnější.
Další funkce
Formulářový framework samozřejmě umí i spoustu dalších věcí, kterými jsem příklad nechtěl zatěžovat:
- Další pole - Nabízí nám další formulářová pole,
jako
ListBox
,FileBox
,PasswordBox
a podobně. - Částečný rendering - Formulář lze vyrenderovat i po částech, když chceme např. jiný layout, někde obrázek nebo nadpisy, rozdělit formulář na více stránek, nějaká speciální JavaScriptová tlačítka a tak dále.
- Více formulářů - Knihovna se jednoduše vypořádá s několika formuláři na jedné stránce.
- Načtení jen části dat - Metodou
getData()
můžeme získat i jen část dat. To využijeme v případě, když jsou ve formuláři pole, která do databáze ukládat nechceme (např. captcha). - Naplnění formuláře daty - Metodou
setData()
naplníme formulář výsledkem dotazu z databáze, což se využije např. při editaci záznamů.
A to hlavní: Knihovna je minimalistická a je navržena tak, aby ji šlo jednoduše rozšiřovat a upravovat. To vše by nás mělo dostatečně motivovat k jejímu využití.
Příště, v lekci Tvorba formulářového frameworku v PHP - HtmlBuilder, se pustíme do první pomocné třídy, kterou bude HtmlBuilder.