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

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.

Seriál: Symfony po krůčkách (18 dílů)

  1. Symfony po krůčkách – Event Dispatcher 30.11.2015
  2. Symfony Console jako první rande se Symfony 7.12.2015
  3. Symfony po krůčkách – Filesystem a Finder 14.12.2015
  4. Symfony po krůčkách – Paralýza možností? OptionsResolver tě zachrání 21.12.2015
  5. Symfony po krůčkách – spouštíme procesy 4.1.2016
  6. Symfony po krůčkách – Translation – překlady jednoduše 11.1.2016
  7. Symfony po krůčkách – Validator (1) 18.1.2016
  8. Symfony po krůčkách – Validator (2) 25.1.2016
  9. Symfony po krůčkách – Routing 1.2.2016
  10. Symfony po krůčkách – MicroKernel 9.2.2016
  11. Konfigurujeme Symfony pomocí YAMLu 16.2.2016
  12. Symfony po krůčkách – oblékáme MicroKernel 23.2.2016
  13. Symfony po krůčkách – ClassLoader 29.2.2016
  14. Symfony po krůčkách – Twig 8.3.2016
  15. Symfony po krůčkách – Twig II. 15.3.2016
  16. Symfony po krůčkách – DomCrawler a CssSelector 23.3.2016
  17. Symfony po krůčkách – HTTP fundamentalista 12.4.2016
  18. Symfony po krůčkách – ušli jsme pořádný kus 19.4.2016

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

PHP vývojář a nadšenec pro open source. S frameworkem Symfony začal pracovat v době vydání jeho druhé verze a od té chvíle na něm staví většinu svých projektů. Pomáhá budovat českou Symfony komunitu a také Symfony framework školí.

Komentáře: 4

Přehled komentářů

MarekL
Petr Jaša Re:
Javier Eguiluz
Petr Jaša Re:
Zdroj: https://www.zdrojak.cz/?p=17087