Použití Nette/Schema pro validaci uživatelského vstupu?

Toanir
Člen | 57
+
+3
-

Ahoj vespolek.

Hrozně se mi líbí balík Schema a myslím si že bych ctěl použít buď jej anebo nějaký jemu podobný pro validaci generického vstupu od uživatele.
Narazil jsem ale na průšvich při komplementaci prvku Structure, že se rovnou sestavuje chybová hláška pro zobrazení, zatímco já bych se potřeboval dostat na strukturovaný pole chybných fieldů, tj chtěl bych nějaký takový případ

$pizzaSchema = Expect::structure([
  'topping' => Expect::structure([
    'ingredients' => Expect::listOf(Expect::anyOf(['mushroom', 'ham', 'pineapple'])),
    'addCHeese' => Expect::bool(false),
  ]),
]);

$pizzaRequest = [
  'topping' => [
    'ingredients' => ['strawberry'],
    'addCheese' => 1,
  ],
];

try {
  $processor = new Processor();
  $pizzaOrder = $processor->process($pizzaSchema, $pizzaRequest);
} catch (ValidationException $ex) {
  // chtěl bych něco jako $errors = $ex->getErrors() :
  // $errors = [
  //  'topping' => [
  //    'ingredients' => [
  //      ['error' => 'schema.anyOf.invalidValue', 'possibleValues' => ['mushroom', 'ham', 'pineapple'],
  //    ],
  //  ],
  // ];
}

Jelikož ale mám ale k dispozici pouze $ex->getMessages(), který vrací už sestavený zprávy k zobrazení, a zatím jsem Schema viděl použitý jen při sestavování DI kontejneru, nejsem si jistej jestli je schéma určený pro použití za runtime třeba na API.

Chci se proto zeptat, jestli se dá Schema použít pro takový případy anebo budu muset šáhnout po něčem jiným

Pavel Janda
Člen | 943
+
0
-

@Toanir Tyjo, to je docela dobrý point. :) Například většina validátorů JSON-SCHEMA vyhodí na konci validace seznam všech chyb, zanořeně, přesně, jak to píšeš. 👍

David Grudl
Nette Core | 7417
+
0
-

Ty všechny informace tam jsou a stačí je předat do té výjimky. V jakém by to mělo být formátu?

Toanir
Člen | 57
+
0
-

Myslím že u samotných chyb stačí kategoricky uchovávat jakýsi errorType, tedy kód chyby, a jakýsi errorData, tedy doplňující informace pro chybu.

Tady bych bral ohled na lokalizaci a kód chyby formátovat s ohledem na modulární rozšiřitelnost.. například <modul>.<validačníPravidlo>.<chyba>.

Pak bych si pro chybu

$error = [
  'errorCode' => 'schema.anyOf.UnexpectedValue',
  'errorData' => [
    'value' => 'apple',
    'suggestedValue' => 'pineapple',
    'allowedValues' => '["mushroom", "ham", "pineapple"]'
  ],
];

mohl v rámci translatoru specifikovat třeba

schema:
  anyOf:
    unexpectedValue: Neplatná hodnota
    # nebo
    unexpectedValue: Neplatná hodnota '%value%', neměli jste na mysli '%suggestedValue%'
    # nebo
    unexpectedValue: Neplatná hodnota '%value%', možné hodnoty jsou %allowedValues%

Editoval Toanir (29. 5. 2020 19:45)

Felix
Nette Core | 1072
+
0
-

Kdyby se v ramci exception dala struktura proiterovat, tak by to bylo pekne. To je fakt. :-)

David Grudl
Nette Core | 7417
+
0
-

Zkusil jsem dát nástřel do masteru, podívejte se na to. Zdrojové informace získáte z $e->getErrors().

Toanir
Člen | 57
+
0
-

Tak na to koukám a v podstatě je to to, co bych čekal.
Nejsem si ale jistej, jak je použitelnej ten kód v jeho aktuálním formátu.

Použitím FQN třídy zajistíme unikátnost ale abych to mohl použít pro vlastní zprávy, potřebuju:

  • explodovat code,
  • namapovat FQN na nějaký prefix pro mojí implementaci translatoru
  • slepit to s částí za dvojtečkou
  • prohnat to translatorem

Asi bych dokázal v aplikaci najít místo, kde tohle dělat aby to vypadalo čistě. Řekl bych ale, že bych se tomu chtěl, s ohledem na návrh knihovny, vyhnout.

Myslím, že by se už při přidávání chyby na kontext mohl použít jakýsi API-ready formát, aby to bylo jednoduše použitelný a neprozrazovalo to nic o struktuře naší (PHP) aplikace.

Kdybysme už při přidávání chyby rozhodli že kód bude třeba to schema.anyOf.unexpected, byl to obyčejný řetězec který by out of the box fungoval s typickým překládacím řešením? (Za typický řešení považuju kdyby/translate resp contributte/translation)

U takovýho přístupu mě napadají alespoň dvě otázky:

  • jak sestavovat kódy?
  • vadí nám případný kolize?

Podle mýho názoru by stačilo kódy psát co nejstručnější a nejdeskriptivnější.
Kolize prefixů bych spíš neřešil protože většinu případů pokryjou samotný elementy už obsažený v nette/schema a vlastní implementace Schema si pojede vlastní prefixy.
Nadhodil bych návrh na finální úpravu: https://github.com/…hema/pull/19

Jen mě ještě tak napadá, že se změnilo api metody addError, což je potenciální BC break

jikki
Člen | 59
+
0
-

Ahoj,

chci nette/schema použít pro validaci importovaného excel souboru. Validaci dat provedu bez problému, nicméně chci uživateli zobrazit jak by měl importovaný excel soubor vypadat, např. jaká by měl mít záhlaví, jaká data, atd. Info chci to generovát ze schématu, nikoliv psat ručně. Pokud se změní schéma, tak se změní i zobrazované info uživateli. A tady narážím na problém, že vlastně zřejmě nedokážu schéma zpětně přečíst.

Exustuje způsob jak schéma zpětně přečíst?

díky moc