Zachycení exception vyhozené z loadHttpData
- hlupec
- Backer | 8
Ahoj,
řeším problém, kdy chci ve formulářovém prvku v metodě setValue vyhodit exception při nevalidní hodnotě (po odeslání formuláře). Zaboha ale nemůžu přijít na to, kde takovou výjmku odchytit. V podstatě stejný případ se musí řešit pokud u nějakého potomka ChoiceControl chci mit enabled „checkDefaultValue“ – když je tam nějaká nepovolená hodnota, vyhodí se výjmka … kde jí chytnu? Třeba abych jí mohla přidělit formuláři pomocí addError?
Mám pocit, že mi uniká nějaká banalita:D
- Polki
- Člen | 553
Všichni ti géniové, co dávají mínusy by měly radši dávat
řešení.
Ok řešení je to co jsem psal a tedy
public function __construct(string $label = null)
{
parent::__construct($label);
$this->addRule([self::class, 'validateMethod'], 'Wrong value');
}
public static function validateMethod(): bool
{
// some logic
return $result;
}
Díky čemuž nemusí nikde vyhazovat výjimky a validita dat se ověřuje opravdu až ve validaci a nad formulářem už se jím chtěná ‚addError‘ zavolá sama automaticky. Stejně tak daný validátor se dá použít i jinde než jen v daném formuláři, jelikož je to funkce, kterou můžeme volat odevšad a jelikož je statická, tak ji dokáže Nette spárovat s JS, takže máme i validaci na straně klienta. Za mě je toto řešení víc ok, než nějak modifikovat funkci onValidate a trápit se s tím co kde mám jak odchytit někde z HTTP requestu, nebo nastavování apod. Tohle udělá všechnu práci čistě, rychle a tehdy, kdy je potřeba. Samo Nette to takovým způsobem dělá například pro validaci E-mailu, Integeru apod. Nechápu tedy, co je na tom špatně pokud tedy podle vás géniů není špatně i samo Nette.
Jestli máte lepší řešení není problém, ale dávat palce bez vysvětlení, nebo navedení jak to je dobře můžou akorát lidi, co tomu sami nerozumí, nebo jen chtějí být cool.
Editoval Polki (1. 11. 2021 19:43)
- hlupec
- Backer | 8
Polki napsal(a):
Všichni ti géniové, co dávají mínusy by měly radši dávat řešení.
Ok řešení je to co jsem psal a tedy
Diky moc. Ja tuhle moznost validace samozrejme znam, ale zeptam se tedy jinak: zapomente na ten muj pripad a zamerte se na tu vyjmku, kterou vyhazuje metoda setValue u inputu dedenych z ChoiceControl. Pokud se nastavuje hodnota ktera neexistuje v poli moznosti, vyhodi se vyjmka – protoze nevim, kde ji chytit, tak by to vzdy koncilo server errorem. To prece nemohl byt zamer ne? (btw ted to resim tak, ze si u vsech techto inputu nastavuju checkDefaultValue(false) :))
- David Grudl
- Nette Core | 8227
hlupec napsal(a):
Jak s tím souvisí loadHttpData?
Jde o metodu setValue, ktera se vola z metody loadHttpData – zminila jsem to jen proto, aby bylo jasne kde se ta metoda vola (ze jde o nacitani z POSTu).
Tak pokud setValue vyhazuje výjimku a loadHttpData volá setValue, tak by tu výjimku mělo zachycovat loadHttpData, ne?
hlupec napsal(a):
: zapomente na ten muj pripad a zamerte se na tu vyjmku, kterou vyhazuje metoda setValue u inputu dedenych z ChoiceControl.
ChoiceControl ale nevolá v loadHttpData metodu setValue
- Polki
- Člen | 553
hlupec napsal(a):
Diky moc. Ja tuhle moznost validace samozrejme znam, ale zeptam se tedy jinak: zapomente na ten muj pripad a zamerte se na tu vyjmku, kterou vyhazuje metoda setValue u inputu dedenych z ChoiceControl. Pokud se nastavuje hodnota ktera neexistuje v poli moznosti, vyhodi se vyjmka – protoze nevim, kde ji chytit, tak by to vzdy koncilo server errorem. To prece nemohl byt zamer ne? (btw ted to resim tak, ze si u vsech techto inputu nastavuju checkDefaultValue(false) :))
Pokud nejde o validaci dat jako takových, ale o vychozí chování Nette,
tak to se chová tak jak má. Například když se ty snažíš jako výchozí
hodnotu něco, co není v možnostech ChoiceControlu, tak to správně
odfiltruje a vyhodí Error 500, jelikož jsi udělala chybu ty
na straně serveru, jelikož se snažíš poslat nevalidní data.
Pokud ale pošle uživatel tvého formu nesmyslný vstup, tak se stane to, že
tento nesmyslný vstup je odfiltrován pryč a jako hodnota se nastaví null viz
funkce getValue a tedy projde i onSuccess
s kódem 200OK.
Pokud ti nevalidní data z formuláře po odeslání vyhazují 500, tak je chyba na tvé straně v implementaci a tedy je třeba zjistit, proč to chybu vyhazuje, protože Nette na tom podíl nemá.
- hlupec
- Backer | 8
Nevim jestli by aplikace mela spadnout. Priklad: v administraci produktu mam select pro vyber kategorii – admin si vybere kategorii XYZ, jenze mezi tim, kdy nacetl formular a tim kdy ho odeslal, jiny admin kategorii XYZ smazal. Pak se prvnimu adminu vyhodi server error – podle me by se to melo nejak dat zachytit.
Ale ok, vysledek diskuze mi staci – zachytit to nelze → musim se vydat jinou cestou. Diky vsem.
Edit: jeste koukam do toho ChoiceControl – je pravda ze tam se metoda setValue v loadHttpData nevola (i kdyz jinde jo), takze by se to melo zachytavat asi v metode createComponentXyzForm.
Editoval hlupec (2. 11. 2021 5:22)
- Milo
- Nette Core | 1283
@hlupec Pokud by aplikace nespadla a běžela dál, došlo by
nevědomky ke ztrátě informace. Tím, že jako programátor nastavíš
checkDefaultValue(false)
už tak nějak počítáš s tím, že se
ti tam může dostat nevalidní hodnota a ta se zahodí.
Rozumím, že ve tvém případě je to pouze komplikace, ale ta se dá snadno vyřešit. Pro výběr kategorie si můžeš udělat vlastní form control. Zhruba:
final class CategorySelect extends SelectBox
{
public function setValue($value)
{
try {
parent::setValue($value);
} catch (Nette\InvalidArgumentException) {
parent::setValue(null);
$this->addError("Kategorie '$value' není k dispozici.");
}
}
}
nebo obecně zhruba:
final class SafeSelectBox extends SelectBox
{
public function __construct(private Closure $onInvalidValue, $label = null, array $items = null)
{
parent::__construct($label, $items);
}
public function setValue($value)
{
try {
parent::setValue($value);
} catch (Nette\InvalidArgumentException $e) {
parent::setValue(null);
($this->onInvalidValue)($this, $value, $e);
}
}
}