8. díl - Tvorba formulářového frameworku v PHP - Motivace

PHP Knihovny Tvorba formulářového frameworku v PHP - Motivace American English version English version

Vítejte u dalšího dílu seriálu tutoriálů o tvorbě PHP knihoven. V dnešním dílu začneme pracovat na větší, ač stále 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, nicmné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

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 by vypadal asi 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 asi takto:

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->addListBox('nahon', 'Náhon', true, false)
        ->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 - Další formulářová pole, jako ListBoxy, FileBoxy, PasswordBoxy a další.
- Částečný rendering - Formulář lze vyrenderovat i po částech, když chcete 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 podobně.
- 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ůžete získat i jen část dat. To využijete v případě, když jsou ve formuláři pole, které do databáze ukládat nechcete (např. captcha).
- Naplnění formuláře daty - Metodou setData() naplníte 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. Doufám, že jsem vás dostatečně namotivoval, příště se pustíme do první pomocné třídy, kterou bude HtmlBuilder.


 

  Aktivity (2)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (13 hlasů) :
4.923084.923084.923084.923084.92308


 


Miniatura
Všechny články v sekci
Knihovny pro PHP

 

 

Komentáře

Avatar
jDanek
Člen
Avatar
jDanek:

Tu šílenou podmínku by jsi mohl zjednodušit

if (isset($_POST['jmeno'], $_POST['jmeno'], $_POST['znacka_vozu'], $_POST['nahon'], $_POST['zpusob_platby'], $_POST['poznamka'], $_POST['vybava'])....
 
Odpovědět 11.10.2014 23:06
Avatar
blablabla
Člen
Avatar
blablabla:

Ahoj, můžete mi poradit nějaký dobrý již hotový formulářový framework?

 
Odpovědět 3.11.2014 19:08
Avatar
blablabla
Člen
Avatar
Odpovídá na Martin Konečný (pavelco1998)
blablabla:

A něco co není závislé na Nette?

 
Odpovědět 3.11.2014 19:19
Avatar
Odpovídá na blablabla
Martin Konečný (pavelco1998):

Nette\Forms :D

Nemusíš stahovat celý FW, formuláře by na něm neměly být závislé.

 
Odpovědět 3.11.2014 19:38
Avatar
Radim Sückr
Redaktor
Avatar
Odpovídá na blablabla
Radim Sückr:

Nette už na sobě závislé není a lze snadno používat jeho jednotlivé části samostatně. https://github.com/nette

 
Odpovědět 3.11.2014 19:49
Avatar
tomichi
Redaktor
Avatar
tomichi:

Chtěl bych jen zdůraznit že autor použíá globální proměnné které nejsou v pohodě. vzhledem k bezpečnosti

$_POST

Navíc nette vede člověka hezkou cestou jak tuhle častou situaci vyřešit s validací. Jednou z mnohých řešení je kouknout na metodu -> addRule() která kontroluje zda to co se předalo je ok. Či napsat si krásně novou třídu FormValidator který bude obsahovat metody na validaci a při vytváření trídy formu si ji předat v konstruktoru a nasledně vytvoříš krásnou metodu ve form třídě ve ktere využiješ metody z ValidatorForm třídy a kterou si callbackem předáš do closure $form->onValidat[] = $this->validateForm; :) ber to spíš jako námět k mnoha zlepšením

Editováno 28.11.2015 10:37
Odpovědět  -1 28.11.2015 10:35
Dělte se o svou zkušenost, je to cesta jak dosáhnout nesmrtelnosti. Dalajláma
Avatar
sam hud
Člen
Avatar
sam hud:

Ďakujem za obrovskú prácu odvedenú na týchto tutoriáloch. Až po podrobnejšom štúdiu si začínam uvedomovať, čo všetko ešte neviem.

Odpovědět 5. srpna 21:03
Kde je vule, tam je i cesta
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na tomichi
David Čápka:

Očividně jsi článek ani nečetl, používání $_POST je právě odstrašující příklad toho, jak to tu dělat nebudeme.

Odpovědět 19. září 10:29
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 9 zpráv z 9.