Symfony po krůčkách – Paralýza možností? OptionsResolver tě zachrání

Abychom podpořili klidnou vánoční náladu, vybrali jsme pro dnešní díl jednu z nejjednodušších Symfony komponent – OptionsResolver. Co to je? `Array_replace` na steroidech. Oproti němu má navíc pár užitečných metod – ty se postarají o to, aby hodnoty byly validní, a zajistí i normalizaci.

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

Kdy se OptionsResolver hodí?

1.  Jestli jsi někdy navrhoval REST API, možná znáš:

<?php

$options = [
    'page' => isset($input['page']) ? $input['page'] : 1,
    'type' => isset($input['type']) ? $input['type'] : 'product'
];

2. Nebo jsi dělal CLI aplikaci, která má mnoho vstupních hodnot – jako např. PHP_CodeSniffer:

$ php phpcs [-nwlsaepvi] [-d key[=value]] [--colors] [--no-colors] [--report=<report>] [--report-file=<reportFile>] [--report-<report>=<reportFile>] [--report-width=<reportWidth>] [--generator=<generator>] [--tab-width=<tabWidth>] [--severity=<severity>]...

3. A nebo modul se složitějším nastavením – jako např. rozšíření pro Doctrine:

// config.yml / config.neon
doctrine:
    orm:
    database: …
    password: …
    port: …
       entity_manager:
          one:
             ...

Co mají tyto příklady společného?

Mají mnoho vstupních hodnot:

  • ty mohou nabývat různých stavů
  • potřebují validaci typu (např. řetězec, číslo…,) nebo vůči seznamu hodnot (např. buď „ano“ nebo „ne“)
  • vyžadují normalizaci, aby se s nimi dále pracovalo lépe (např. doplnění relativní cesty na absolutní)
  • někdy mají defaultní hodnoty, jindy ne

Takový jednoduchý validátor jistě zvládne napsat každý. Jestli jsi ale v situaci, kdy s kódem pracuje více lidí, hodí se zvolit nějaké ověřené řešení. To by mělo mít dokumentaci a určité normy.

V těchto situacích ti přijde vhod OptionsResolver.

Jak vypadá použití v praxi?

Použití v praxi najdeš u ApiGenu. Pokud ho neznáš, Je to CLI aplikace, která generuje API dokumentaci zdrojového kódu.

Jako vstup má až přes 20 možností různých typů, mezi nimi pole, text nebo bool.

Každá nevalidní hodnota vede k ukončení běhu aplikace. S tím nám OptionsResolver pomůže. Jak? Mrkni na třídu ConfigurationOptionsResolver.

Krátký příklad

Vrátíme se k úvodnímu příkladu s REST API:

$options = [
    'page' => isset($input['page']) ? $input['page'] : 1,
    'type' => isset($input['type']) ? $input['type'] : 'clothes';
];

Na něm si ukážeme 3 hlavní featury této komponenty:

  • nastavení defaultních hodnot
  • validaci
  • normalizaci

Nejdříve si komponentu nainstalujeme přes composer:

$ composer require symfony/options-resolver

Přidáme autoloader a vytvoříme novou instanci OptionsResolveru:

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

// $input = …;

$optionsResolver = new Symfony\Component\OptionsResolver\OptionsResolver;

1. Nastavení defaultních hodnot

Výše uvedené použití isset() nahradí metoda setDefaults():

$optionsResolver->setDefaults([
    'page' => 1,
    'type' => 'clothes'
]);

$options = $optionsResolver->resolve($input);

Co to udělá se vstupy?

$input = [];
// $options: 'page' => 1, type' => 'clothes'

$input = ['page' => 2];
// $options: 'page' => 2, 'type' => 'clothes'

$input = ['missing’ => 5];
// Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException

Přesně tak, OptionsResolver nám ošetří hodnoty, které nejsou povolené. To nám pomůže k lepší bezpečnosti aplikace.

Pro tip: Jako defaultní hodnotu můžeš použít i callback.

$optionsResolver->setDefault('page', function (Options $options) {
    return ('clothes’ === $options['type']) ? 1 : 2;
});

Pro tip 2: A jestli chceš přidat možnost bez defaultní hodnoty, tak takhle:

$optionsResolver->setDefined('wrapper');

2. Validace

Někde nám chce někdo zadat data, o která zrovna nestojíme. Pojďme si je zvalidovat.

$optionsResolver->setAllowedTypes('page', 'int');

Můžeme přidat i více typů:

$optionsResolver->setAllowedTypes('page', ['int', 'float']);

Povolené hodnoty taxativně vyjmenovat:

$optionsResolver->setAllowedTypes('page', [1, 2, 3, 4, 5]);

Nebo stejné omezení jako výše, ale zapsané pomocí callbacku:

$optionsResolver->setAllowedTypes('page', function ($value) {
     return $value >= 1 && $value <= 5;
));

3. Normalizace

Co to znamená? Normalizace je jakákoliv úprava dat po tom, co byla zvalidována. V našem případě zajistíme, aby se při vyžádání větší než povolené stránky zobrazila 10. strana.

$optionsResolver->setNormalizer('page', function ($options, $value) {
    $maxPage = 10;
    if ($value > 10) {
        return $maxPage;
    }

    return $value;
});

A jsi zase o krok dál…

Dnes jsme si ukázali komponentu, která nám v chaosu mnoha možností pomůže udržet jasný směr.

Teď už víš, že OptionsResolver ti umožní:

  • nastavit defaultní hodnoty
  • validovat vstupy
  • normalizovat hodnoty, pokud potřebují ještě nějaké modifikace
  • a že se hodí při psaní složitější CLI aplikace, REST API nebo nějaké konfigurace

 

Chceš vědět víc?

Potřebuješ poznat OptionsResolver do hloubky? Mrkni na oficiální dokumentaci.

 

Příští pondělí si dáme vánoční volno a pak budeme v seriálu opět pokračovat.

Krásné Vánoce vám všem!

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 8

Přehled komentářů

tacoberu Positivní
Tomáš Votruba Vyzkoušej
soundczeck Díky
Tomáš Votruba Rádo se děje
radoslavius
Tomáš Votruba Re: ParamFetcher
Diskobolos Autore clanku, proc...
Tomáš Votruba Proč Nette => Symfony?
Zdroj: https://www.zdrojak.cz/?p=16993