17
cze

symfony: sfValidatorChoice i ciągły błąd „Invalid.”.

Witajcie. Dzisiaj po raz kolejny zmierzymy się z frameworkiem symfony, a konkretnie z jego „wewnętrznym frameworkiem” obsługującym formularze. Jak już zdążyliście się dowiedzieć z kilku wcześniejszych wpisów, jest on bardzo wygodnym narzędziem, jednak jeśli się o pewnych rzeczach po prostu nie wie, to niestety potrafi być także złośliwy i ogłupia programistę niezrozumiałymi komunikatami. Tak też właśnie jest z walidatorem pola <select> – sfValidatorChoice, który niestety potrafi zmarnować cenny czas programisty wodząc go za nos komunikatem „Invalid”.

Fotografia: m-a-c, CC-BY.

symfony: sfValidatorChoice i ciągły błąd „Invalid.”.

Weźmy pod uwagę prosty przykład:

// (...)
$options = array(
	'0' => '14 days',
	'1' => '7 days',
	'2' => '3 days',
	'3' => '1 day',
	);
$this->setWidgets(array(
	// (...)
	'option'  => new sfWidgetFormSelect(array(
		'choices' => $options,
		'default' => 0,
		)),
	// (...)
	));
// (...)
$this->setValidators(array(
	// (...)
	'option' => new sfValidatorChoice(
		array(
			'choices' => $options
			),
		),
	// (...)
	));

Wydawałoby się, że wszystko jest ok, w końcu podaliśmy do konfiguracji pola opcje w relacjach id => nazwa elementu, a także te same dane do walidatora.

Co jednak otrzymamy? Otóż, niezależnie od tego, co wybierzemy z naszej listy w polu <select>, walidator zawsze zwróci komunikat „Invalid.” – oczywiście może być to dowolna inna, ustawiona przez nas wiadomość, co nie zmienia faktu, że formularz nie ma szans przejść walidacji.

Wydawałoby się, że jeśli sam framework nie prostestuje w kwestii otrzymanej konfiguracji, to wszystko powinno bez problemu się uruchomić i zadziałać według naszych oczekiwań. Nic bardziej błędnego – okazuje się, że dane przekazywane do walidatora są nieco inne niż te, których oczekuje pole formularza. Walidator oczekuje samych „kluczy” z tablicy opcji przekazanych do pola. Należy zatem potraktować rzeczoną tablicę funkcją array_keys() i problem zostaje magicznie rozwiązany:

$this->setValidators(array(
	// (...)
	'option' => new sfValidatorChoice(
		array(
			'choices' => array_keys($options),
			),
		),
	// (...)
	));

Podsumowanie.

Z jednej strony twórcy frameworka podjęli dobrą decyzję o takiej, a nie innej implementacji tego walidatora. W końcu nie musi on mieć informacji na temat tego, co się będzie wyświetlało – jego interesują tylko i wyłącznie dane wynikowe przekazane do skryptu obsługującego formularz.

Z drugiej strony jednak uważam, że jest to pewna niekonsekwencja, ponieważ przekazanie tych samych danych do pola formularza i walidatora ma sens „logiczny” – jednemu bytowi mówimy: „idź, wyświetl mi ten zbiór danych”, a drugiemu: „słuchaj, sprawdź, czy ten zbiór danych jest poprawny”. Poza tym, w przypadku programisty, który pierwszy raz styka się z tym problemem jest to o wiele bardziej zrozumiałe i przewidywalne, a więc jeden potencjalny problem mniej. Inną sprawą jest to, że posiadając gotową tablicę, możemy ją po prostu wykorzystać w innym miejscu, a wywołanie array_keys() to zawsze trochę czasu i pamięci „do tyłu”. Oczywiście nie namawiam nikogo do tego typu mikrooptymalizacji, aczkolwiek strata kilku mikrosekund bez wyraźnego celu nie będzie nigdy zbyt szczęśliwym rozwiązaniem.

Dziękuję za wspólnie spędzony czas i zapraszam do dyskusji w komentarzach.

Warto przeczytać.

Trwa ładowanie…

Subscribe without commenting

Wyszukaj:
Twitter
http://t.co/piYQJA2z /cc @merowing_ you'll like it :)
3 days ago
"It is about being polite, respectful and kind. That's the open source currency. Can't pay in these values? You shouldn't be using it."
4 days ago
Facebook
© Copyright 2010-2012 Tomasz Kowalczyk. All rights reserved. Created by Dream-Theme — premium wordpress themes. Proudly powered by WordPress.