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í.

11. diel - Dokončenie triedy FormControl v PHP

V minulej lekcii, FormControl - Predok pre formulárové kontrolky v PHP , sme si začali práce na triede FormControl, ktorá je predkom pre všetkých formulárové kontrolky. Dnes triedu dokončíme.

Pretože sme si pridali metódu addPatternRule (), môžeme teraz v ďalších pravidlách overovať regulárne výrazy. To využijeme napr. U pravidlá pre minimálnu dĺžku hodnoty:

Pravidlo minimálnej dĺžky

public function addMinLengthRule($minLength, $validateClient = true, $validateServer = true)
{
    return $this->addPatternRule('.{' . $minLength . ',}', $validateClient, $validateServer);
}

Pravidlo heslá

Ďalej pridáme pravidlo pre validáciu hesla. Heslo bude musieť byť dlhšia ako 6 znakov, čo vyriešime pridaním pravidlá s PATTERN. Ďalej nebude smieť obsahovať diakritiku, čo overíme pre zjednodušenie až na serveri.

public function addPasswordRule($validateClient = true, $validateServer = true)
{
    $this->addMinLengthRule(6, $validateClient);
    return $this->addRule(array(
        'type' => self::RULE_PASSWORD,
        'message' => 'Heslo nesmí obsahovat diakritiku a musí být dlouhé alespoň 6 znaků.',
    ), $validateClient, $validateServer);
}

Pravidlo pre dátum a čas

Nakoniec pridajme trojicu metód pre pridanie pravidlá na dátum a čas, dátum samotný a samotný čas. Pre každé pravidlo pridáme opäť pattern.

public function addDateTimeRule($validateClient = true, $validateServer = true)
{
    $this->addPatternRule('[0-3]?[0-9]\.[0-1]?[0-9]\.[0-9]{4}\s[0-2]?[0-9]\:[0-5]?[0-9](\:[0-5]?[0-9])?');
    return $this->addRule(array(
        'type' => self::RULE_DATETIME,
        'format' => DateUtils::DATETIME_FORMAT,
        'message' => 'Hodnota musí být ve formátu: dd.mm.yyyy hh:mm(:ss)',
    ), $validateClient, $validateServer);
}

public function addDateRule($validateClient = true, $validateServer = true)
{
    $this->addPatternRule('[0-3]?[0-9]\.[0-1]?[0-9]\.[0-9]{4}');
    return $this->addRule(array(
        'type' => self::RULE_DATETIME,
        'format' => DateUtils::DATE_FORMAT,
        'message' => 'Hodnota musí být ve formátu: dd.mm.yyyy',
    ), $validateClient, $validateServer);
}

public function addTimeRule($validateClient = true, $validateServer = true)
{
    $this->addPatternRule('[0-2]?[0-9]\:[0-5]?[0-9](\:[0-5]?[0-9])?');
    return $this->addRule(array(
        'type' => self::RULE_DATETIME,
        'format' => DateUtils::TIME_FORMAT,
        'message' => 'Hodnota musí být ve formátu: hh:mm(:ss)',
    ), $validateClient, $validateServer);
}

Povinný súbor

Metódy zakončíme pravidlom pre nahranie povinného súboru.

public function addFileRequiredRule($validateClient = true, $validateServer = true)
{
    return $this->addRule(array(
        'type' => self::RULE_REQUIRED_FILE,
        'message' => 'Soubor je povinný',
    ), $validateClient, $validateServer);
}

Pravidiel by sa samozrejme dalo vymyslieť ešte veľa, ale neskoršie kombináciou týchto som docielil zatiaľ všetkého, čo som potreboval. A keby niečo náhodou nestačilo, vždy sa dajú jednoducho pridať. Určite by sme však ich počet mali držať na absolútnom minime, pravidlá s rovnakým mechanizmom budeme z týchto ešte neskôr odvodzovať v triede Form.

Validácia

Kontrolke teda môžeme pridať niekoľko pravidiel. Teraz napíšeme tú časť triedy, ktorá bude jednotlivé pravidlá overovať. Ako už bolo povedané, budeme to robiť 2x, raz na strane klienta a raz na strane servera.

Klientská časť

Metóda nižšie pridá kontrolke HTML atribúty podľa validačných pravidiel, ktoré obsahuje. Budeme využívať atribútov HTML 5, veľmi jednoducho tak overíme regulárne výrazy, povinné polia a maximálnu dĺžku.

public function addClientParams()
{
    foreach ($this->rules as $rule)
    {
        if ($rule['validate_client'])
        {
            switch ($rule['type'])
            {
                case self::RULE_REQUIRED:
                case self::RULE_REQUIRED_FILE:
                    $this->htmlParams['required'] = 'required';
                    break;
                case self::RULE_MAX_LENGTH:
                    $this->htmlParams['maxlength'] = $rule['max_length'];
                    break;
                case self::RULE_PATTERN:
                    if (!isset($this->htmlParams['pattern']))
                        $this->htmlParams['pattern'] = $rule['pattern'];
                    break;
            }
        }
    }
}

HTML 5 bohužiaľ nevie viac patternov a tak sa bude overovať len prvý. Pokiaľ bude mať pole niekoľko ďalších (čo sa mi asi ešte nestalo), overí sa až na serveri.

Serverová časť

Podobný switch umiestnime aj do metódy checkRule (), ktorá overuje jedno pravidlo na serveri. Všimnite si, že používame knižnice DateUtils a StringUtils, ktoré sme si predtým vytvorili.

private function checkRule($rule)
{
    $name = $this->name;
    switch ($rule['type'])
    {
        case self::RULE_REQUIRED:
            return isset($_POST[$name]) && (is_numeric($_POST[$name]) || !empty($_POST[$name]));
        case self::RULE_MAX_LENGTH:
            return !isset($_POST[$name]) || !$_POST[$name] || mb_strlen($_POST[$name]) <= $rule['max_length'];
        case self::RULE_PATTERN:
            return !isset($_POST[$name]) || !$_POST[$name] || preg_match('~^' . $rule['pattern'] . '$~u', $_POST[$name]);
        case self::RULE_REQUIRED_FILE:
            return isset($_FILES[$name]) && isset($_FILES[$name]['name']) && $_FILES[$name]['name'];
        case self::RULE_DATETIME:
            return !isset($_POST[$name]) || !$_POST[$name] || DateUtils::validDate($_POST[$name], $rule['format']);
        case self::RULE_PASSWORD:
            return !isset($_POST[$name]) || !$_POST[$name] || ((StringUtils::removeAccents($_POST[$name]) == $_POST[$name]) && (mb_strlen($_POST[$name]) >= 6));
    }
    return false;
}

Ak pravidlo zlyhá, budeme chcieť, aby sa kontrolka podfarbil červeno. K tomuto účelu triede pridajme verejný atribút $ invalid:

public $invalid;

Validácia zakončíme vrcholnú metódou checkValidity (), ktorá overí všetky pravidlá a ak niektoré neplatí, nastaví invalid na true, pridá CSS triedu invalid a vyvolá výnimku:

public function checkValidity()
{
    foreach ($this->rules as $rule)
    {
        if (($rule['validate_server']) && (!$this->checkRule($rule)))
        {
            $this->invalid = true;
            $this->addClass('invalid');
            throw new UserException($rule['message']);
        }
    }
}

Triedu UserException budeme používať pre všetky výnimky, ktorej správa je určená pre užívateľov. Kód triedy je nasledujúci:

class UserException extends Exception
{

}

Rendering

Renderovanie (generovanie HTML kódu pre kontrolku) budeme realizovať abstraktné metódou, ktorú si každá konkrétna kontrolka implementuje po svojom. Zároveň však budeme chcieť, aby sa tesne po zavolaní renderovanie pridali kontrolke klientskej validačný parametre. Z toho dôvodu necháme metódu potomka ako protected a zavoláme ju z verejnej render ():

protected abstract function renderControl($isPostBack);

public function render($validateClient, $isPostBack)
{
    if ($validateClient)
        $this->addClientParams();
    return $this->renderControl($isPostBack);
}

Načítanie a uloženie dát

Zostáva ešte dodať nejaké rozhranie pre ukladanie a načítanie dát z / do kontrolky. Budeme rovno počítať s tým, že kontrolka môže obsahovať viac hodnôt a nie len jednu. Môžeme tak realizovať napr. Checklist, čo je kontrolka, obsahujúci niekoľko checkbox. Výhodou viac polí v jednej kontrolke je ľahšie tvorba formulára.

Dodajme metódu getData (), ktorá vráti dáta v kontrolke. Ak bola nejaká hodnota odoslaná na server (v $ _POST je kľúč s názvom kontrolky), tak vráti tú, inak nevráti nič. Aby sme zachovali koncept vracania viac hodnôt, vrátime vždy pole. Kontrolky s viacerými políčkami si túto metódy potom prepíšu, tým klasickým bude postačovať.

public function getData()
{
    return isset($_POST[$this->name]) ? array($this->name => $_POST[$this->name]) : array();
}

Podobne urobme metódu, ktorá vracia kľúče všetkých polí v kontrolke:

public function getKeys()
{
    return array($this->name);
}

Funkcia na nastavenie hodnoty bude už závisieť na potomkovi a preto ju len predpíšeme ako abstraktný:

public abstract function setData($key, $value);

Tým máme základ kontroliek hotový. Nabudúce, v lekcii Formulárový framework v PHP - InputBox , si napíšeme prvú kontrolku, ktorú bude InputBox. Hotová a zdokumentovaná trieda FormControl je k stiahnutiu v prílohe.


 

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é 447x (2.83 kB)
Aplikácia je vrátane zdrojových kódov v jazyku php

 

Predchádzajúci článok
FormControl - Predok pre formulárové kontrolky v PHP
Všetky články v sekcii
Knižnice pre PHP
Preskočiť článok
(neodporúčame)
Formulárový framework v PHP - InputBox
Č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