Best practice: obsluha formulářů

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
David Grudl
Nette Core | 8218
+
0
-

Životní cyklus formuláře se skládá:

  1. z jeho definice
  2. nastavení výchozích hodnot
  3. vykreslení uživateli
  4. validace
  5. získání dat

Existují v podstatě dva způsoby, jak cyklus implementovat: s využitím událostí nebo bez.

Bez obsluhy událostí

Doporučuji tento vzor:

// definice
$form = new Form();
$form->addText('name', 'Your name:');
$form->addSubmit('ok', 'Send');
$form->addSubmit('cancel', 'Cancel');

// byl odeslán?
if ($form->isSubmitted()) {
	if ($form['cancel']->isSubmittedBy()) {
		// process cancelled
		redirect(...);
	}
	if ($form['ok']->isSubmittedBy() && $form->isValid()) {
		// submitted and valid
		save($form->getValues());
		redirect(...);
	}

} else {
	// první zobrazení, nastavíme výchozí hodnoty
	$form->setDefaults($defaults);
}

Tento způsob je vhodný pro použití v jednoduchých webových stránkách, kde se nevyužívá MVC.

S obsluhou událostí

Doporučuji tento vzor:

// definice
$form = new Form();
$form->addText('name', 'Your name:');
$form->addSubmit('ok', 'Send')
	->onClick[] = 'OkClicked'; // nebo 'OkClickHandler'
$form->addSubmit('cancel', 'Cancel')
	->setValidationScope(FALSE)
	->onClick[] = 'CancelClicked'; // nebo 'CancelClickHandler'
// alternativa:
$form->onSubmit[] = 'FormSubmitted'; // nebo 'FormSubmitHandler'


if (!$form->isSubmitted()) {
	// první zobrazení, nastavíme výchozí hodnoty
	$form->setDefaults($defaults);
}

// zavolej obslužné handlery, pokud je formulář odeslán
$form->fireEvents();


// obslužné handlery:
function OkClicked(SubmitButton $button)
{
	// submitted and valid
	save($form->getValues());
	redirect(...);
}

function CancelClicked(SubmitButton $button)
{
	// process cancelled
	redirect(...);
}

function FormSubmitted(Form $form)
{
	// manual processing
	if ($form['cancel']->isSubmittedBy()) ...
}

Tento způsob je vhodný pro použití v MVC implementacích jako Nette\Application.

Obslužný handler pro onSubmit lze použít v případě, kdy formulář nemá žádné nebo právě jedno tlačítko. V odstatních situacích bývá vhodnější využít handler onClick přímo na tlačítku.

Handler onClick se volá před handlerem onSubmit. Handlery se volají pouze v případě, že je odeslání validní. Pokud odeslání validní není, volají se handlery pro události onInvalidClick a onInvalidSubmit. Uvnitř metody OkClicked tedy není nutné ověřovat validitu formuláře. Naopak metoda FormSubmitted může být zavolána i v případě nevalidního formuláře, byl-li odeslán tlačítkem Cancel.

V případě, že formulář nebyl odeslán tlačítkem (například byl odeslán přes JavaScript), nebo se tak tváří kvůli chybě v Internet Exploreru, bude Nette za odesílací tlačítko považovat první tlačítko formuláře. Tudíž obsluha přes události onClick je spolehlivá.

Obslužné handlery se vyvolají při prvním volání metody fireEvents(), při použití uvnitř Nette\Application vyvolání zajistí samotný presenter.


Přesměrování

Po odeslání POST formuláře a zpracování dat vždy přesměrujte na další stránku (v presenteru metodou redirect). Zamezíte tak situaci, že uživatel stisknutím tlačítka F5 nebo procházením historie v prohlížeči omylem odešle formulář znovu.

Callback

V uvedených ukázkách jsou jako handlery použity funkce, samozřejmě pokud píšete objektový kód, je vhodnější volat metody (zejména ve spojení s Nette\Application). Handler je nutno zapsat jako PHP typ callback, takže v případě použití v presenteru například jako $form->onSubmit[] = array($this, 'FormSubmitted').

Vitek Jezek
hledá kolegy | 285
+
0
-

znesvetim tento Best practice otazkou – mohu nejak v obsluznych handlerech brat promene, ktere jsou v kodu pred zavolanim obsluznych handleru (tedy ve funkci, ktera tvori form/vola handlery)?

Zatim to obchazim pres persistentni parametry, ale urcite by to slo vice Nette (cti [vice ciste / elegantne / lepe]) : )
David Grudl
Nette Core | 8218
+
0
-

Pokud obslužné handlery představují metody objektu, tak můžeš používat třeba proměnné objektu.