Přejít k navigační liště

Zdroják » PHP » Symfony po krůčkách – Validator (1)

Symfony po krůčkách – Validator (1)

Články PHP

V dnešním díle se podíváme na zoubek Symfony komponentě Validator. Tato komponenta slouží pro validaci dat – ověření toho, že hodnoty našich proměnných jsou správného typu, spadají do daného rozsahu hodnot nebo splňují jiná pravidla, která si nadefinujeme.

Nálepky:

Aby nebyl článek příliš dlouhý, díl o komponentě Validator rozdělíme na dvě části. Dnes si v článku ukážeme, jak validovat skalární hodnoty, pole a jak zajistit překlady chybových zpráv. V příští části se podíváme na validaci objektů a skupiny validačních pravidel.

Zdrojový kód všech příkladů uvedených v tomto článku najdete v repozitáři na GitHubu

Jak začít s komponentou Validator

Komponentu Validator nainstalujeme pomocí nástroje Composer:

composer require symfony/validator

Nyní ji můžeme použít ve svém scriptu. Začněme jednoduchou validací, kdy ověříme, jestli uvedená hodnota není prázdná.

require_once __DIR__ . '/vendor/autoload.php';

use Symfony\Component\Validator\ValidatorBuilder;
use Symfony\Component\Validator\Constraints\NotBlank;

$builder = new ValidatorBuilder();
$validator = $builder->getValidator();

$violations = $validator->validate('', new NotBlank());
echo (string) $violations;

A to je celé. Po spuštění skriptu bychom měli vidět výpis s oznámením “This value should not be blank.”

Asi jste si všimli, že náš validátor jsme vytvořili pomocí objektu třídy VaidatorBuilder. Je to z toho důvodu, že třída Validator závisí na dalších třídách a vytvoření její instance není při prvním setkání s ní úplně triviální. ValidatorBuilder nám instanci validátoru vytvoří s výchozím nastavením bez jakýchkoli problémů a my tak můžeme náš nový validátor okamžitě s radostí používat.

Metoda validate

Stěžejní částí příkladu je volání metody validate(). Tato metoda očekává 3 argumenty, z toho pouze 1. je povinný. Ten představuje hodnotu, kterou chceme validovat. Může to být objekt, pole nebo skalární hodnota. V našem případě předáváme jednoduchou hodnotu, a to prázdný řetězec.

Jako druhý argument očekává metoda validační pravidlo, což je objekt typu Constraint, proti kterému chceme hodnotu validovat. Můžeme předat i pole více pravidel, čímž validátoru řekneme, že chceme, aby hodnota splňovala všechna uvedená pravidla. V našem případě předáváme pouze pravidlo NotBlank, které ověřuje, jestli hodnota není prázdná.

Zamysleme se nyní nad úkolem, kdy bychom chtěli ověřit, jestli je hodnota IP adresa. Pomocí validátoru je ověření snadné. V první řadě musíme zkontrolovat, jestli hodnota není prázdná, a za druhé, jestli se skutečně jedná o IP adresu. Podívejte se na následující ukázku:

// result: This value should not be blank.
echo (string) $validator->validate('', [new NotBlank(), new Ip()]);

// result: This is not a valid IP address.
echo (string) $validator->validate('22.gg.54.00', [new NotBlank(), new Ip()]);

// result: No violations
echo (string) $validator->validate('192.168.54.1', [new NotBlank(), new Ip()]);

Třetí argument je tzv. skupina. Ta nám určuje, jaká skupina validačních pravidel se má pro právě spouštěnou validaci použít. U každého validačního pravidla totiž můžeme zadat skupinu, do které patří, a jednoduše tak pravidla seskupovat. Více se k tomuto tématu dostaneme v příštím díle u validování objektů, kde definování skupin dává asi největší smysl.

Výsledkem volání metody validate() je seznam všech nalezených chyb proti námi uvedeným pravidlům. Tyto chyby jsou typu ConstraintViolation a obsahují informace o pravidle, které nebylo splněno, chybovou hlášku a několik dalších údajů.

Je to e-mail nebo IBAN?

Velkou výhodou komponenty Validator je její arzenál validačních pravidel, které v základu programátorům nabízí. V příkladu jsme použili validační pravidlo NotBlank a Ip. Je jich ale mnohem více. Jako příklad můžeme uvést e-mail, Url, Regex, Country, Iban, Callback, a další. Jejich kompletní seznam i s popisem konfigurace najdete v dokumentaci

Validace polí

Validace hodnoty je fajn. Často ale potřebujeme validovat hodnoty celých datových struktur. I na to Validator myslí. Pojďme se podívat na trochu zajímavější příklad validace asociativního pole hodnot. Takové pole můžeme například dostat z formuláře zaslaného HTTP požadavkem.

require_once __DIR__ . '/vendor/autoload.php';

use Symfony\Component\Validator\ValidatorBuilder;
use Symfony\Component\Translation\Translator;

use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\Type;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\CardScheme;

$inputData = [
   'name' => 'Jan',
   'age' => 20,
   'card' => '5111111111111111',
   'email' => 'name@provider.com',
];

$violations = $validator->validate($inputData, new Collection([
   'name' => [
       new NotBlank(),
   ],
   'age' => [
       new NotBlank(),
       new Type([
           'type'=>'integer'
       ]),
       new Range([
           'min' => 18,
           'max' => 80,
           'minMessage' => "You must be at least {{ limit }} years old to enter.",
           'maxMessage' => "You are too old. Entering is not safe for you. It Is only for persons younger than {{ limit }}",
       ]),
   ],
   'card' => [
       new NotBlank(),
       new CardScheme([
           'schemes' => ['MASTERCARD', 'VISA'],
       ]),
   ],
   'email' => [
       new NotBlank(),
       new Email(),
   ],
]));

echo (string) $violations;

Vidíme, že princip validace je stejný. Opět voláme metodu validate(). Nyní ovšem do této metody místo skalární hodnoty předáváme celé pole a jako validační pravidlo používáme objekt typu Collection, díky kterému můžeme nadefinovat validační pravidla pro jednotlivé prvky pole. Všimněte si, že při vytváření validačních pravidel můžete do jejich konstruktoru předat pole s nastavením, čímž si každé pravidlo můžete přizpůsobit svým potřebám.

Vezměme si například validační pravidlo Length. Tomu jsme nastavili hodnotu ‘min’ a ‘minMessage’. Tímto jsme řekli, že požadujeme, aby hodnota ‘note’ byla delší než 20 znaků a pokud to tak nebude, chceme o tom uživatele informovat zprávou „Your note must have at least 20 characters“, kde {{ limit }} se nahradil hodnotou uvedenou pod klíčem ‘min’.

Překlady chybových zpráv

Některé z vás by mohlo zajímat, jak se řeší překlady chybových zpráv. Zvídavější si už možná všimli, že při instalaci komponenty Validator se do složky vendor nainstalovala i komponenta Translator, na níž Validator závisí. Ve výchozím stavu používá Validator pro překlady objekt typu IdentityTranslator, který přímo nic nepřekládá, pouze ve zprávách nahrazuje případné zástupné parametry.

Pokud chcete, aby Validator používal váš vlastní Translator, vytvořte si jej podle postupu, jak jste se to naučili v předchozím díle seriálu, a předejte ho do objektu typu ValidatorBuilder. Bude to vypadat nějak takto:

require_once __DIR__ . '/vendor/autoload.php';

use Symfony\Component\Validator\ValidatorBuilder;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\ArrayLoader;
use Symfony\Component\Validator\Constraints\NotBlank;

// translator
$translator = new Translator('cs_CZ');

$translator->addLoader('array', new ArrayLoader());

$translator->addResource('array', [
    'person.name.not_blank' => 'Hodnota nesmi byt prazdna!',
], 'cs_CZ');

$translator->addResource('array', [
    'person.name.not_blank' => 'Value should not be blank!',
], 'en_EN');

// validator
$builder = new ValidatorBuilder();
$builder->setTranslator($translator);
$validator = $builder->getValidator();

// validation rule
$notBlank = new NotBlank([
    'message' => 'person.name.not_blank'
])
// validation and result in czech
echo (string) $validator->validate('', $notBlank);

// validation and result in english
$translator->setLocale("en_EN");
echo (string) $validator->validate('', $notBlank);

V ukázce si nejdříve vytvoříme translator a načteme překlady. Překlady definujeme pomocí zástupného klíče. Pro přehlednost definujeme pouze jeden klíč ‚person.name.not_blank‘. Je dobré vědět, že každé validační pravidlo z komponenty Validator nám umožňuje nastavit si vlastní zprávu, která se uživateli zobrazí v případě chyby. Zpráva se validačnímu pravidlu nastavuje přes klíč ‚message‘. My v ukázce u pravidla NotBlank místo konkrétní zprávy použijeme právě zástupný klíč z definice překladů.

Zase o krok dál

V dnešním díle jsme si ukázali:

  • jak nainstalovat a začít používat Validator
  • jak validovat samostatné skalární hodnoty
  • jak validovat složitější datové struktury jako pole
  • jak lokalizovat chybové hlášky

Kam jít dál?

Seznam validačních pravidel a jejich možnosti konfigurace najdete na stránkách Symfony v sekci referencí.

Při rozšiřování Validátoru o vlastní validační pravidla se můžete inspirovat v CookBooku.

Začínáš se Symfony a chceš se rychle posunout dál? Přijď si popovídat na některé z našich setkání v Praze, Brně nebo Ostravě, také se můžeš zúčastnit našeho školení.

Komentáře

Subscribe
Upozornit na
guest
4 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
MarekL

Aj ked to viac menej poznam, pekne vysvetlene, diky ;)

Javier Eguiluz

Thank you very much for publishing this article! I’m reading the entire series (with Google Translate help) and I love it. As a very minor issue, I’d like to say that some elements are lacking the „“ tag to differentiate them from the regular text.

Anyway, thank you and keep up with the good work.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.