IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

9. diel - Tvorba formulárového frameworku v PHP - HtmlBuilder

V minulej lekcii, Tvorba formulárového frameworku v PHP - Motivácia , sme si vysvetlili, že vďaka použitiu frameworku pre obsluhu formulárov budeme túto časť aplikácie programovať niekoľkokrát rýchlejšie. V dnešnom dieli si vytvoríme jednoduchú triedičku pre renderovanie HTML kódu.

Motivácia

MVC je síce pekná vec, ale v našich aplikáciách budeme narážať aj na situácie, keď potrebujeme často renderovať malé úseky HTML kódu alebo renderovať taký HTML kód, kde množstvo prezentačné logiky prekoná samotný objem HTML kódu. Použitie šablón je tu možné, ale nemusí byť vždy efektívne, preto budeme renderovať HTML priamo.

Urobme si jednoduchý príklad. Budeme chcieť vyrenderovať HTML kód selectu, ktorý vyzerá nasledovne:

<label for="znacka-vozu">Značka vozu</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>

Chceli by sme, aby sa select vyrenderoval pomocou nejakej PHP metódy. Zatiaľ si metódu predstavme ako statickú na nejakom helper, volali by sme ju asi takto:

<?= FormHelper::renderSelect('znacka-vozu', 'Značka vozu', true, array(
    'Škoda' => 'skoda',
    'BMW' => 'bmw',
    'Audi' => 'audi',
)) ?>

Že podobnú metódu pre prácu s formulármi potrebujeme by malo byť jasné, pretože pole možností často získavame z databázy a so statickým HTML by sme si teda nevystačili.

Implementácia metódy by mohla vyzerať nasledovne:

<?php
public static function renderSelect($name, $title, $required, $data)
{
    $html = '<label for="' . htmlspecialchars($name) . '">' . htmlspecialchars($title) . '</label>';
    $html .= '<select name="' . htmlspecialchars($name) . '" id="' . htmlspecialchars($name) . '" ';
    if ($required)
        $html .= 'required="required"';
    $html .= '>';
    foreach ($data as $title => $value)
    {
        $html .= '<option value="' . htmlspecialchars($value) . '">' . htmlspecialchars($title) . '</option>';
    }
    return $html . '</select>';
}

V kóde som zanedbal označenie vybranej položky. Kód je začiatočnícky a trpí mnohými neduhmi. HTML sa zle zvýrazňuje, pretože je ako obyčajný string, sme odkázaní na ručné ošetrovanie hodnôt pomocou PHP funkcie htmlspecialchars () a všetko zneprehľadňuje konkatenace reťazca do premennej $ html.

HtmlBuilder

Trieda HtmlBuilder vychádza z princípu SAX, ktorý sa používa pre zápis XML súborov. Odtieňuje nás od samotnej HTML syntaxe a generovanie kódu zjednodušuje na prácu s jednotlivými elementmi. Vnútorne sa HTML samozrejme zostavuje podobne, ako sme si to ukázali vyššie. Výhodou však je, že zvonku s ním pracujeme ako s elementy a nie ako s reťazcom.

Ukážme si vyrenderované selectu pomocou HtmlBuilderu:

public static function renderSelect($name, $title, $required, $data)
{
    $builder = new HtmlBuilder();
    $builder->addValueElement('label', $title, array(
        'for' => $name,
    ));
    $selectAttributes = array(
        'name' => $name,
        'id' => $name,
    );
    if ($required)
        $selectAttributes['required'] = 'required';
    $builder->startElement('select', $selectAttributes);
    foreach ($data as $title => $value)
    {
        $builder->addValueElement('option', $title, array(
            'value' => $value,
        ));
    }
    $builder->endElement();
    return $builder->render();
}

Pracujeme iba s elementmi a polí ich atribútov. Všetko sa spája a ošetruje samo, máme minimum možností niečo pokaziť. Výsledkom je totožný HTML kód s tým na začiatku článku.

Implementácia

Pripravme si triedu HtmlBuilder a rovno do nej vložme dva privátne atribúty. Bude sa jednať o zostavovaný HTML reťazec a zásobník otvorených párových elementov. Vďaka zásobníku vieme, ktorý element sme naposledy otvorili a môžeme ho tak jednoducho uzavrieť bez uvedenia jeho názvu.

class HtmlBuilder
{
    private $html = '';
    private $elementStack = array();

}

Triedu si samozrejme ako vždy komentujte. Pridajme privátne metódu k vyrenderované elementu:

private function renderElement($name, $htmlParams, $pair)
{
    $this->html .= '<' . htmlspecialchars($name);
    foreach ($htmlParams as $key => $value)
    {
        $this->html .= ' ' . htmlspecialchars($key) . '="' . htmlspecialchars($value) . '"';
    }
    if (!$pair)
        $this->html .= ' /';
    $this->html .= '>';
    if ($pair)
        array_push($this->elementStack, $name);
}

Metóde odovzdáme názov elementu, jeho HTML parametre a či je párový. Metóda vytvorí jeho HTML reťazec a pripojí ho do výsledného HTML. Ak je element párový, uložíme si do zásobníka že je otvorený.

Pomocou tejto privátnej metódy vytvoríme niekoľko verejných:

public function addElement($name, $htmlParams = array())
{
    $this->renderElement($name, $htmlParams, false);
}

public function startElement($name, $htmlParams = array())
{
    $this->renderElement($name, $htmlParams, true);
}

public function addValue($value, $doNotEscape = false)
{
    $this->html .= $doNotEscape ? $value : htmlspecialchars($value);
}

public function endElement($name = null)
{
    if (!$name)
        $name = array_pop($this->elementStack);
    $this->html .= '</' . htmlspecialchars($name) . '>';
}

function addValueElement($name, $value, $htmlParams = array(), $doNotEscape = false)
{
    $this->startElement($name, $htmlParams, true);
    $this->addValue($value, $doNotEscape);
    $this->endElement();
}

Predstavme si, čo ktoré metódy robia:

  • addElement () vyrendruje jednoduchý nepárový element.
  • startElement () otvorí párový element.
  • addValue () pridá HTML kód a to buď do otvoreného elementu alebo pokojne mimo neho. Môžeme si zvoliť, či sa má hodnota prevádzať na entity alebo nie.
  • endElement () uzavrie posledný otvorený párový element. Môžeme uviesť aj meno v prípade, že by sme chceli uzatvárať nejaký element, ktorý otvorila napr. Iné inštancie Builder.
  • addValueElement () otvorí párový element, vloží do neho hodnotu a potom ho uzavrie.

Výsledné HTML vráti metóda render ():

public function render()
{
    return $this->html;
}

Máme hotovo. Okomentované trieda je k stiahnutiu v prílohe. V budúcej lekcii, FormControl - Predok pre formulárové kontrolky v PHP , začneme práce na predkovi pre kontrolky formulára.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 517x (3.69 kB)
Aplikácia je vrátane zdrojových kódov v jazyku php

 

Predchádzajúci článok
Tvorba formulárového frameworku v PHP - Motivácia
Všetky články v sekcii
Knižnice pre PHP
Preskočiť článok
(neodporúčame)
FormControl - Predok pre formulárové kontrolky v PHP
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity