Jak obejít striktní kontrolu formulářových polí v Nette

Vycházím z příkladu: Web běží již několik let a programátoři si moc nelámali hlavu se striktními hodnotami, takže v databázi se velmi často odkazuje na neexistující hodnoty. Nyní web chceme modernizovat a postavit ho na Nette frameworku. Narazíme na problém striktní kontroly formulářových polí

Select může mít hodnoty:
0 - NE
1 - ANO

V aplikaci ovšem máme uloženu například hodnotu 2. Co se stane pokud se tuto hodnotu budeme snažit vložit
při $form->setDefaults($values); ? Na produkčím serveru nám to shodí celou aplikaci s error 500, což je velmi nežádoucí. Jako lepší řešení v tomto případě považuji si chybné hodnoty logovat a napravovat postupně. Hodnotám, které jsou mimo rozsah bude přiřazena hodnota NULL.
 
Uvedené řešení jsem psal pro opravdu velký formulář, kde bylo více než 100 formulářových polí, takže by nemělo smysl je ošetřovat po jednom. A řešení bylo psáno pouze pro 3 typy - CheckboxList, SelectBox a RadioList. Ostatní pole jako Checkbox, MultiSelectBox, ChoiceControl, MultiChoiceControl, ... ve formuláři nebyly, takže nejsou řešeny.

// unset bad options
foreach ($form->getComponents() as $component) {
	if ($component instanceof \Nette\Forms\Controls\CheckboxList) {
		$options = $component->getItems();
		foreach ($defaults[$component->name] as $key => $value) {
			if (!array_key_exists($value, $options)) {
				unset($defaults[$component->name][$key]);
				if (!empty($value)) {
					Tracy\Debugger::log("Value {$value} for codebook {$component->name} doesn't exists.", Tracy\ILogger::WARNING);
				}
			}
		}
	}

	if (
		$component instanceof \Nette\Forms\Controls\SelectBox ||
		$component instanceof \Nette\Forms\Controls\RadioList
	) {
		$options = $component->getItems();
		if (!empty($defaults[$component->name])) {
			if (!array_key_exists($defaults[$component->name], $options)) {
				if (!empty($defaults[$component->name])) {
					Tracy\Debugger::log("Value {$defaults[$component->name]} for select/radio {$component->name} doesn't exists.", Tracy\ILogger::WARNING);
				}
				$defaults[$component->name] = NULL;
			}
		}
	}
}

$form->setDefaults($defaults);


Tímto způsobem můžeme opravovat chybné hodnoty v aplikaci postupně bez vyhazování chybových hlášek uživateli.

 

Na závěr ještě přidávám další užitečný skript. Můžete tímto způsobem také zakázat všechna formulářová pole v Nette - například pro uživatele, který může formulář vidět, ale nemůže ho upravovat.

if ( ! $user_can_edit) {
	foreach ($form->getComponents() as $component) {
		$component->setDisabled();
	}
}