Automatická validace parametrů v presenteru pomocí anotací

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Jan Tvrdík
Nette guru | 2595
+
0
-

Implementoval jsem automatickou validaci parametrů v presenteru pomocí @param anotací.

/**
 * @param bool
 * @param int|array
 * @param string
 */
public function renderFoo($a, $b = FALSE, $c = NULL) {...}

Stručná pravidla chování v tomto případě:

  1. Pokud $a bude '1' nebo '0', bude automaticky přetypován na boolean.
  2. Pokud $a není ani boolean ani '1' nebo '0', skončí skript s BadRequestException.
  3. Pokud $a nebude existovat nebo bude NULL, skončí skript s BadRequestException.
  4. Pokud $b bude např. '123', bude automaticky přetypován na int.
  5. Pokud $b nebude existovat nebo bude NULL, bude dosazena výchozí hodnota, tj. FALSE.
  6. Pokud $b nebude ani celé číslo ani celočíselný řetězec ani pole, skončí skript s BadRequestException.
  7. Pokud $c nebude řetězec, skončí skript s BadRequestException.
  8. Pokud $c nebude existovat nebo bude NULL, bude dosazena výchozí hodnota, tj. NULL.

Zdrojový kód je k dispozici ve dvou variantách na GitHubu (varianty se liší tím, co ještě dovolí automaticky konvertovat).

Protože to může potenciálně způsobovat BC break*, tak je potřeba do BasePresenteru umístit public $validateParams = TRUE; pro explicitní zapnutí validace. Časem možná sepíši RFC (důvody a problémy).

Chtěly byste něco takového v Nette? Sepsal jsem RFC.


*V případě, že používáte anotaci @param a její hodnota je chybná, nebo nepočítáte s automatickým přetypováním, nebo spoléháte na dříve fungující přetypování hodnoty na typ výchozí hodnoty, pokud existuje.

Editoval Jan Tvrdík (28. 2. 2011 23:52)

Michalek
Člen | 209
+
0
-

Asi blbá otázka, ale nevyčetl jsem to přímo. Pokud by se anotace neuvedly, fungovalo by to standardně, tedy bez kontroly? Nebo je vynuceno používání všude? Dík :)

Filip Procházka
Moderator | 4668
+
0
-

Líbilo by se mi automatické přetypování, ale validace si rád dělám přímo v metodě.

Jan Tvrdík
Nette guru | 2595
+
0
-

Pokud anotace nebude uvedena, bude se to chovat normálně s tím rozdílem, že nebude fungovat automatické přetypování na typ výchozí hodnoty (to je v Nette teď).

Honza Marek
Člen | 1664
+
0
-

Je to takové magické, ale to je ostatně ten trik s přetypováním podle výchozí hodnoty taky.

Inza
Člen | 330
+
0
-

Jsem jednoznačně PRO zaintegrování do Nette! A pokud je implementačně reálné to udělat tak, že pokud by se @param anotace neuvedly, tak by se to chovalo jako se to chová nyní, bylo by to řešení, které IMHO řeší vše.

A pro hnidopichy, kteří neradi „magické“ věci, tam klidně můžeme ponechat tu nutnost tuto featuru zapnout v BasePresenteru…

Aurielle
Člen | 1281
+
0
-

PRO zaintegrování! Zrovna tohle je fičurka, kterou si zase jakýkoliv vývojář usnadní psaní presenterů a nebude muset validovat parametry sám. Skvělá práce!

Nox
Člen | 378
+
0
-

Předpokládám že přetypování NULL ⇒ false je kvůli analogickému pojetí v issetu null = neexistuje
Mě osobně toto přijde spíš podivné, ale když už to takto je v samotným PHP, tak to asi teda nechat…

…i když ono null=„prázdné“…no…je to tak na hraně

Každopádně pěkná práce

mkoubik
Člen | 728
+
0
-

Taky se mi to líbí, i když to moc nevyužiju (radši validuju ručně v metodě, kvůli možnosti redirectu, logování atd). Ale myslím, že by byl lepší jiný název anotace, nebo to zapínání v BasePresenteru, aby to nekolidovalo s phpdocem.

jtousek
Člen | 951
+
0
-

Jsem rozhodně PRO. Jen bych měl drobný dotaz, když u některého parametru chci umožnit hodnotu NULL, musím přímo uvést např. @param int|NULL?

Bylo by hezké, kdyby se stejně chovaly i perzistentní parametry komponent (tedy i presenterů). Tam by to samozřejmě nebylo podle anotace @param, ale podle @var.

Jan Tvrdík
Nette guru | 2595
+
0
-

mkoubik napsal(a):

Myslím, že by byl lepší jiný název anotace, aby to nekolidovalo s phpdocem.

Jaký smysl by mělo deklarovat něco jiného v @param, než chci skutečně validovat? Zvolená anotace zcela úmyslně odpovídá phpDoc.

jtousek napsal(a):

Jsem rozhodně PRO. Jen bych měl drobný dotaz, když u některého parametru chci umožnit hodnotu NULL, musím přímo uvést např. @param int|NULL?

Pokud chceš umožnit hodnotu NULL, použij např. @param int|NULL. Pokud chceš, aby byl daný parametr nepovinný (což bude výrazně častější případ), deklaruj mu jako výchozí hodnotu NULL.

Samu skutečnost, kdy Nette umožňuje poslat NULL do povinného parametru, považuji za velmi podivnou.

jtousek
Člen | 951
+
0
-

Špatně jsem se vyjádřil, měl jsem na mysli nepovinné parametry. :) Jestli Nette umožňuje předat přímo NULL nevím.

mkoubik
Člen | 728
+
0
-

Jaký smysl by mělo deklarovat něco jiného v @param, než chci skutečně validovat? Zvolená anotace zcela úmyslně odpovídá phpDoc.

Například chci v dokumentaci uvést typ, ale validovat chci ručně.

Jan Tvrdík
Nette guru | 2595
+
0
-

Hodnoty výchozích parametrů se nevalidují, takže tam lze uvést i něco, co neodpovídá anotaci.

Jan Tvrdík
Nette guru | 2595
+
0
-

mkoubik napsal(a):

Jaký smysl by mělo deklarovat něco jiného v @param, než chci skutečně validovat? Zvolená anotace zcela úmyslně odpovídá phpDoc.

Například chci v dokumentaci uvést typ, ale validovat chci ručně.

V tom případě si tu validaci nezapínej vůbec nebo uveď nakonec |mixed, čímž validaci daného parametru zrušíš.

Honza Marek
Člen | 1664
+
0
-

Co si myslíte o tom, že by se validace zapínala další anotací? Potom odpadne riziko, že to někomu bude dělat něco co nechce. Na druhou stranu je to více psaní a na tu anotaci lze zapomenout a přesto na ni spoléhat.

/**
 * @ValidateParams
 * @param bool
 * @param int|array
 * @param string
 */
public function renderFoo($a, $b = FALSE, $c = NULL) {...}
Jan Tvrdík
Nette guru | 2595
+
0
-

Co takhle kompromis? – V BasePresenteru se nastaví výchozí chování a zvláštní anotací u dané metody lze toto výchozí chování přepsat.

Honza Marek
Člen | 1664
+
0
-

To mi přijde rozumné.

Jan Tvrdík
Nette guru | 2595
+
0
-

Nebude lepší přejmenovat tu proměnnou v Presenteru z $validateParams na $autoValidateParams (analogie k $autoCanonicalize)?

Ohledně těch anotací mě napadá @enableParamsValidation a @disableParamsValidation, ale je to dost dlouhé. Co třeba @paramsValidation on a @paramsValidation off? (Velké písmeno na začátku anotace se mi nelíbí.)

westrem
Člen | 398
+
0
-

Ehm nemam to sice zverejnene ale:

https://forum.nette.org/…-a-validacia#…

;)

Honza Marek
Člen | 1664
+
0
-

JT: proč ne true a false?

Jan Tvrdík
Nette guru | 2595
+
0
-

Subjektivně mi přijde hezčí on a off.

Patrik Votoček
Člen | 2221
+
0
-

Hezké zapínání anotací na první pohled cool na druhý vůbec (sem strašně línej proto volím cestu nastavením v base presenteru). Jinak taky bych raději true/false nez on/off (jsem programátor stejně jako počítám od nuly tak nepoužívám ano/ne yes/no nebo on/off na to mám prostě true/false – ostatní připadá v úvahu pouze u více jak 2 možností a to ještě za předpokladu že tou možností není autodetect kterej se dá řešit pomocí null)

jtousek
Člen | 951
+
0
-

@westrem: Zajímavé, ale většinou nepotřebuješ omezovat id na 30 apod. Výjimka by mohla být třeba že měsíc je 1–12, ale těch případů není tolik aby to bylo potřeba. Automatické přetipování je zde na místě, tvé řešení mi připadá zbytečně komplexní. ;)

K diskusi @ValidateParams / @ParamsValidation / whatever. Anotace by rozhodně měla být boolean true/false. A myslím, že by se měla jmenovat stejně nebo podobně jako samotná proměnná. Např. tedy public $autoValidateParams = TRUE a @ValidateParams false.

Co ty perzistentní parametry? Divím se, že se k tomu nikdo nevyjádřil.

Jan Tvrdík
Nette guru | 2595
+
0
-

jtousek napsal(a):

Co ty perzistentní parametry?

Kouknu, jak složité by to bylo a podle toho se rozhodnu, zda podporu pro jejich validaci dopíšu.

Jan Tvrdík
Nette guru | 2595
+
0
-

Tak jsem sepsal RFC.

Šaman
Člen | 2632
+
0
-

Mě se to líbí a vzhledem k tomu, že se v ostrých dvojkách vyskytuje hodně nekompatibilit, tak bych byl pro, aby se tato funkce spíše ve výjimečných případech vypínala, než aby se muela zapínat.

Kdo anotace píše, ten o ní bude vědět a kdo je nepíše, tomu nepřekáží.

jtousek
Člen | 951
+
0
-

Pokud jde o zapínání vypínání, respektive co z toho je default, imho je to úplně jedno. Stejně je to 1 řádek v BasePresenteru. ;)