Realizuję w tym momencie bardzo przyjemny projekt – przyjemny dlatego, że powstaje „od zera” i mam możliwość wyboru narzędzi, w jakich będę go tworzył. Chciałem spróbować wykorzystać do tego testowany od pewnego czasu framework Symfony2, jednak idąc za radą udzieloną mi przez batmana podczas konferencji 4Developers wracam na „stare śmieci”, czyli stabilną wersję symfony. Jak to bywa przy powrotach – zazwyczaj pojawiają się problemy z ponownym „zgraniem się” programisty z kodem. Tym razem padło na mechanizm walidacji formularzy, który nie do końca chciał współpracować.
Problem: sfValidatorAnd i właściwości „required” komponentów wewnętrznych.
Walidacja formularzy w symfony odbywa się poprzez odpowiednie skonfigurowanie listy walidatorów dla każdego pola. Dostępnych jest wiele tzw. „widgetów” opisujących różne typy pól, a także wiele różnych, mniej lub bardziej ogólnych walidatorów testujących konkretne wymagania dotyczące przetwarzanych danych.
Weźmy pod uwagę przykładową konstrukcję walidatora dla pola „login”:
(...)
'login' => new sfValidatorString(
array('required' => true),
array('required' => 'This field is required.')
),
(...)
Jak widać, do konkretnego pola formularza możemy podpiąć tylko jeden walidator, ze względu na fakt, że klucz „login” może mieć tylko jedną wartość. Wynika to z budowy tablic w językach programowania, gdzie określony identyfikator odpowiada konkretnej wartości [pomijam tutaj funkcjonalności takich bibliotek jak STL i jego klasa std::multimap ;]].
Twórcy symfony pozwalają nam jednak na podpięcie kilku walidatorów do jednego pola za pomocą tzw. „walidatorów agregujących” [ok, sam to wymyśliłem] – klas, przyjmujących jako wymagania… inne wymagania. Są to m. in. komplementarne sfValidatorAnd i sfValidatorOr, których zastosowanie powinno być jasne. W tym wpisie weźmiemy pod uwagę pewien problem związany z pierwszą z wymienionych klas – sfValidatorAnd.
Weźmy pod uwagę przykładowy kod:
(...)
'login' => new sfValidatorAnd(array(
new sfValidatorEmail(
array(),
array('invalid' => 'Invalid email address.')
),
new sfValidatorString(
array('required' => true),
array('required' => 'This field is required.')
),
),
),
(...)
Tak skonfigurowany walidator ma za zadanie:
- Sprawdzić, czy został podany ciąg znaków,
- Sprawdzić, czy podany ciąg znaków jest poprawnym adresem email.
Chciałbym tutaj rozwiać wszelkie wątpliwości – to działa. Problem polega jednak na tym, że ewentualny błąd we wprowadzonych danych powinien się przełożyć bezpośrednio na komunikaty o błędach, także zawarte w kodzie walidatora. O ile komunikat o niepoprawnym adresie email jest „respektowany”, o tyle komunikat „required” elementu sfValidatorString jest zupełnie ignorowany, a potencjalny użytkownik zobaczy jedynie napis „Required.”.
Jak więc to naprawić?
Rozwiązanie: Powtórzenie właściwości „required” w parametrach sfValidatorAnd.
Konstrukcja walidatora w symfony jest w pewnym sensie ustandaryzowana, dlatego zazwyczaj możemy trzymać się następującego schematu:
new sfValidatorCustom( array([parametry walidacji]), array([parametry komunikatów o błędach]) );
„Walidatory agregujące”, ze względu na to, że zawierają inne walidatory, wprowadzają tutaj małą zmianę:
new sfValidatorAggregateCustom( array([lista walidatorów]), array([parametry walidacji]), array([parametry komunikatów o błędach]) );
Jak zatem sugeruje śródtytuł – dodajmy do naszej konstrukcji „And” komunikat określający wynik jego działania jako całości:
'login' => new sfValidatorAnd(array(
new sfValidatorEmail(
array(),
array('invalid' => 'Invalid email address.')
),
new sfValidatorString(
array('required' => true),
array('required' => 'This field is required.')
),
),
array('required' => true),
array('required' => 'This field is required.')
),
W tym momencie nasz walidator zaczyna działać jak należy, reagując poprawnie zarówno na fakt braku danych w określonym polu, jak i jego błędnym formacie.
Warto przeczytać.
Trwa ładowanie…
Która to wartość może być array’em. A ten array może zawierać inne walidatory. Tak więc albo ja nie rozumiem tego co napisałeś, albo niejasno się wyraziłeś ;)
Darmowa płyta miesiąca – kwiecień 2011
A nie lepiej zrobić :
‚login’ => new sfValidatorEmail(
array(‚required’ => true),
array(‚invalid’ => ‚Invalid email address.’, ‚required’ => ‚This field is required.’)
Miałem na myśli to, że do jednego pola można faktycznie podpiąć bezpośrednio tylko jeden walidator, bo podpięty jest jedynie sfValidatorAnd, który faktycznie nie robi nic poza połączeniem swoich składników. A to, co się w nim znajduje, to już nie jest walidator pola, jako taki, tylko element tego podpiętego.
Czy takie wytłumaczenie jest dla Ciebie sensowne?
symfony- sfValidatorAnd i problem z ignorowaniem właściwości „required” komponentów wewnętrznych
I owszem, w podobny też sposób w końcu to napisałem, jednakże początkowy, błędny kod posłużył za materiał na niniejszy wpis.
symfony- sfValidatorAnd i problem z ignorowaniem właściwości „required” komponentów wewnętrznych
Chodzi mi o to, że to co napisałeś sugeruje, że fakt przypięcia jednego walidatora wynika z ograniczeń języka, a nie symfony. A są to zdecydowanie ograniczenia symfony.
Zend-Db – za i przeciw
Racja, mogłem się tutaj wyrazić nieprecyzyjnie. Chociaż przyznam szczerze, że nie próbowałem wrzucać listy walidatorów w arraya – wolę je jednak połączyć sfValidatorAnd czy podobnym.
symfony- sfValidatorAnd i problem z ignorowaniem właściwości „required” komponentów wewnętrznych
Pingback: symfony: klasa sfWidgetFormI18nDate i problem z podawaniem zakresu lat. « Tomasz Kowalczyk
„Chciałem spróbować wykorzystać do tego testowany od pewnego czasu framework Symfony2, jednak idąc za radą udzieloną mi przez batmana podczas konferencji 4Developers wracam na „stare śmieci”, czyli stabilną wersję symfony.”
Stoję właśnie przed podobnym dylematem i rozważam do nowego projektu użycie wersji 2 z racji wejścia w fazę beta, ciekaw jestem jakie argumenty wysunął batman i przekonał Ciebie do skorzystania jednak z wersji 1.4.x?
Wiesz, wtedy, kiedy rozmawiałem z nim Symfony2 było „ledwie” w wersji PR9, także oficjalnie to był jedynie „zarys” frameworka. Teraz w wersji beta o wiele więcej rzeczy jest już stabilnych, poza tym bardzo dużym plusem nowej wersji jest włączona już w gałąź master bibliotekę formularzy. Batman nie wysunął jakichś specjalnie mocnych argumentów, po prostu stwierdził, że na moim miejscu wziąłby wersję stabilną, a ja byłem 50/50, także po prostu jego opinia przeważyła.
Jeśli pytasz o to, czy wchodzić w nową wersję, czy użyć starej, to odpowiem krótko: jeśli to duży projekt, w którym będziesz istotnie polegał na różnych wrażliwych elementach frameworka, to weź starą, sprawdzoną wersję. Nie umniejszając twórcom Symfony2, na pewno znajdą się w niej jeszcze błędy, a według ostatnich słów Fabiena Potenciera jeszcze co najmniej 2 miesiące zanim zobaczymy stabilną wersję. W innym przypadku możesz bez problemu zaryzykować i spróbować nowej.
PHP- Sprawdzanie istnienia adresu email
Dzięki za szybką odpowiedź.
Będzie to większy projekt, a symfony z gałęzi 1.x znam w miarę dobrze, więc chyba zostanę na „starych śmieciach” ;) Natomiat postaram się chyba w wolnym czasie wymyślić jakiś projekt dla siebie, gdzie będę trenował skill’a w Symfony2.
Nie ma sprawy – szczerze mówiąc, mam dokładnie takie samo podejście. Nowymi rzeczami można się bawić do woli, ale w produkcji lepiej polegać na sprawdzonych rozwiązaniach.
Do boju zatem, Tyronie! ;]
PHP- Sprawdzanie istnienia adresu email