Form Boost: experiment, který bude snad někoho zajímat
- redhead
- Člen | 1313
Zdravím,
ani nevím proč, ale zdála se mi jako zajímavá myšlenka oddělit definici formuláře do samostatného souboru a definovat samotný formulář anotacemi. „Blázen!“, říkáte si. A možná i jsem. Jen mě zajímalo, jak by to fungovalo, jak by to vypadalo a jak by se s tím dělalo. Jde tedy hlavně o experiment a já bych rád věděl váš názor.
Po pár hodinách práce mi vyšel tento funkční výsledek:
class RegisterForm {
/**
* @Text(Jméno)
* @Pattern('[a-zA-Z0-9_.]+', msg = Nesprávné uživatelské jméno)
* @MaxLength(12, msg = Délka musí být max. 12)
* @MinLength(2, msg = Délka musí být min. 2)
* @Required(msg = Povinný údaj)
*/
public $username;
/**
* @Password(Heslo)
* @Required(msg = Povinný údaj)
*/
public $password;
/**
* @Password(Heslo znovu)
* @Required(msg = Povinný údaj)
* @Equal(password, msg = Hesla se neshodují)
*/
public $passwordValidation;
/**
* @Text(E-mail, emptyValue = '@')
* @Email(msg = Nesprávný formát emailu, required = false)
*/
public $email;
/**
* @Select(Národnost, prompt = Vyberte)
*/
public $nationality;
public $nationalityItems = array('cz' => 'Česká', 'sk' => 'Slovenská');
/** @Submit('Registrovat') */
public function onSubmit() {
dump($this);
}
}
Propojení s presenterem jsem zatím moc neřešil, zatím zjednodušeně takto:
protected function createComponentForm() {
return FormBoost::from(new RegisterForm);
}
Výhody
- přehlednější kód
- odeslaná data dostaneme přímo v properties objektu, nezabýváme se tedy s polem (bez napovídání)
- default hodnoty můžeme nastavit jednotlivým properties (rovnou nebo konstruktorem)
- renderuje se naprosto stejně jako normální formulář, mohl by se i rozšířit o vlastní šablonu s manuálním vykreslením
- podporuje filtrování hodnot přes callback na
filter<ControlName>($value)
- podle mě je kód o něco kratší, ale může to být jen zdání
Nevýhody
- paradoxně samotné anotace (nenapovídání kódu, překlepy v názvech, možné konflikty)
- zatím bez větší podpory condition, conditionOn apod.
- bez podpory groups a containerů (neřešil jsem, zatím)
- bez podpory wrappers a CSS tříd (neřešil jsem, zatím)
- a všechno ostatní, co jsem ještě neřešil
Co si o tom myslíte? Má vůbec cenu pokračovat dál? (pokračoval bych, kdyby byl zájem a hlavně čas, který ale stejně asi nebude)
- awsickness
- Člen | 98
ma to smysl jen ve spojeni s nejakou db entitou / osobne mam postaveny automaticky generator formularu nad doctrine a na zaklade anotaci takze pak staci jen predat entitu nad kterou chci formular a je to.
- Filip Procházka
- Moderator | 4668
Annotace nad vlastnostmi objektu ano, ale takto asi ne. Nette\Database to neumí, Doctrine s tím kamarádit nebude a jen tak si psát schránky pro formuláře mi přijde zbytečné.
Jelikož používám Doctrine, tak nějaký takovýto builder budu co nevidět potřebovat. Ale naštěstí už mám vyřešení mapování formulářů na entity, takže to bude hračka :)
@**awsickness**: nechceš to někam nahodit? že bych se inspiroval ;)
- voda
- Člen | 561
Mám něco podobného, pracuje to rovnou s entitami. Zatím ve stádiu
vývoje. Většinu věcí to načítá s Doctrine anotací, pro zbytek tam je
@Input
.
Továrnička pak vypadá asi takto:
public function createComponentCreateForm() {
$form = $this->context->formBuilder->build('\Article'); // název třídy nebo entita
$that = $this;
$form->onSuccess[] = function(\Article $article) use ($that) {
$that->context->articleModel->createArticle($article);
$that->flashMessage("Článek byl vytvořen.", 'success');
$that->redirect('default');
};
// tady se může s formulářem dělat cokoliv dalšího
return $form;
}
K vidění na https://github.com/…/FormBuilder
- awsickness
- Člen | 98
hospilan: nemyslim si ze bych neco delal lepe nez ty,ale jen pro zajimavost kam jsem dosel po nekolika mesicich si s tim hrani.
pro kazdy typ v entite jako je string int 1:n m:n jsem si udelal doctrine → form kde prochazim anotaci a pokud najdu jednoduchy typ vytvorim objekt ktery vi jak sam sebe nasetovat pridat filtry … a prida se do daneho formulare.
zpetne to funguje podoben akorad pro values z formulare hledam v metadatech jaky je to ty a novou value predan tomu samemu objektu ktery presne vi co s ni ma delat a kde hledat pripadne objekty.
plus navic umim prepsat annotacni definici kdykoliv vytvarim formular atd.
jedine co ted bojuji ze bychom radi udelali N subform pro navazane entity
napriklad user adresy 1:n tak aby v jednom adresari mel n subformularu pro
adresy. to mi jelo ale nebylo to pekne takze me ceka predelavani.
v pripade zajmu ukazu casti kodu ale bohuzel to nemuzu davat verejne komplet.
- redhead
- Člen | 1313
@awsickness: Pokud to řeší pouze Doctrine anotace, tak se myslím ochudíš o pár pravidel, které Doctrine neřeší (min. length, regexp pattern, závislosti, atp.).
@Nox: Jasně. Popřemýšlím o způsobech, jakým by to šlo řešit a třeba to i půjde. Já jsem tyto komponenty nikdy nepoužil a tak nevím, co všechno potřebují.
@HosipLan: Tak s Nette\Database to ani nemá co
dělat. Navíc se nic neliší od jejího používání i s tímto
objektem – prostě jen místo setDefaults()
to nasetuješ
propertám tohoto objektu (což by se pro result z DB dalo zautomatizovat).
S Doctrine je to pravda, tam to hapruje. Ale nezdá se mi nereálný
využít Doctrine anotace a namapovat je na pravidla ve formulářích. Pak bys
nemusel psát @MaxLentgh
jako to mám teď já, ale vzalo by se to
z definice sloupce. Přiznám se, že Doctrine jsem nikdy nepoužíval, ale
neviděl bych v tom velký problém.
Čili další směřování by bylo asi sjednotit výhody obou – Doctrine anotací a formulářových anotací.
Editoval redhead (21. 3. 2012 11:37)
- awsickness
- Člen | 98
co se tyce FILLTRU samozrejme plne podporuji completni filtry jake ma NETTE staci je zapsat do annotace.
- Honza Marek
- Člen | 1664
Třeba v Symfony řeší podobný problém, ale trochu jinak. Využívají dat z doctrine metadat a z definovaných validačních pravidel (oboje jde zapsat jako anotace třídy). Pak se to používá asi takto (přesnou syntaxi si vůbec nepamatuju):
$form = $formFactory->createFrom('Blabla\Model\Clanek')
->add('name')
->add('description')
->add('publishDate');
if ($form->isSubmitted()) {
$entity = $form->getData();
// ...
}
Výhodou je, že se nemíchá v jedné třídě logika formuláře (submit) a vlastnosti datového objektu formuláře (db entita nebo třída reprezentující data vč. validací).