Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [Symfony] Transformacja danych przed zapisem
mundeck
post
Post #1





Grupa: Zarejestrowani
Postów: 43
Pomógł: 0
Dołączył: 2.09.2012

Ostrzeżenie: (0%)
-----


Chciałbym przed zapisem danych z formularza w Symfony przekształcać je do odpowiedniego formatu. Przykładowo, jeśli użytkownik wpisze numer telefonu "123-123-123" to w bazie powinno być zapisane: "+48123123123". Próbowałem zastosować CallbackTransformer wg dokumentacji, ale to raczej służy formatowaniu w polach formularza, a nie w celu zapisania do bazy. Oczywiście mógłbym stworzyć sobie serwis i wrzucać sobie do niego wartość tego pola, ale czy są może jakieś lepsze, wbudowane w SF rozwiązania?
Go to the top of the page
+Quote Post
Crozin
post
Post #2





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Domyślam się, że Twój formularz pracuje bezpośrednio na obiekcie encji obsługiwanej przez Doctrine, tak? Jeżeli tak to jest to bardzo, bardzo zła praktyka.

1. Przygotuj sobie dedykowany obiekt, który reprezentuje model danych formularza.
2. Możesz wykorzystać DataTransformer dla formularza, który znormalizuje numer telefonu (123-123-123 -> +48123123123).
3. Jeżeli formularz jest prawidłowy wyciągnij sobie encję, zaktualizuj jej dane na podstawie danych z formularza i zapisz ją.
Go to the top of the page
+Quote Post
mundeck
post
Post #3





Grupa: Zarejestrowani
Postów: 43
Pomógł: 0
Dołączył: 2.09.2012

Ostrzeżenie: (0%)
-----


Do każdego formularza mam przygotowany FormType i jeśli pola pokrywają się z polami encji, to ustawiam w setDefaults odpowiednią klasę.

Próbowałem zrobić tak jak w pkt. 2., tylko że efekt jest taki, że transfomer burzy mi domyślną wartość. Domyślna wartość, która pojawia się w polu "Telefon" to "+48", a transformer taką wartość powinien odrzucić (zawiera tylko 3 znaki, więc nie jest to poprawny nr).
Go to the top of the page
+Quote Post
Crozin
post
Post #4





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Tą odpowiednią klasą powinna być osobna, dedykowana klasa pod ten formularz - nie klasa-encja. To, że część pól się pokrywa, to że część będziesz traktować jako jeden-do-jeden jak w encji nie ma specjalnego znaceznia. Wtedy możesz zdecydowanie łatwiej określić sobie reguły walidacji, transformatory, a przede wszystkim specyficzną dla danego formularza logikę - logikę formularza, nie domeny, nie bazodanową.
Go to the top of the page
+Quote Post
mundeck
post
Post #5





Grupa: Zarejestrowani
Postów: 43
Pomógł: 0
Dołączył: 2.09.2012

Ostrzeżenie: (0%)
-----


Pierwszy raz słyszę o takim rozwiązaniu. Nie wiedziałem, że ustawianie encji jako domyślnej klasy formularza jest niezalecane. Na ile zrozumiałem to co jest w dokumentacji (przykład z TaskType) to wlaśnie dzięki temu wszystko odbywa się szybciej i łatwiej, bo nie trzeba zapisywac osobno, ręcznie każdego pola, ani tworzyć tych dodatkowych klas. Myślałem, że taką klasą obsługującą formularz jest już po prostu Form Type.

Tymczasem jednak mam spory problem - dość skomplikowany formularz, który działał dobrze, dopóki nie wziąłem się za walidację. Jedne jego części (embedded forms) są wyświetlane lub nie w zależności od opcji wybranych we wcześniejszych polach (steruje tym jquery), tak samo niektóre dalsze pola są włączane i wyłączane w zależności od wyboru. Myślałem, że jeśli wyłącze pola tej składowej formularza, która jest chowana to ominę walidację, ale tak się nie dzieje. W efekcie schowana część formularza jest walidowana i formularz nie przechodzi, bo nic tam nie było wpisane.

Szczerze mówiąc mam wrażenie, że o ile dla prostych formularzy typu "zapisz notkę na blogu" komponent Form działa prosto, intuicyjnie i szybko można go ogarnąć, o tyle dla bardziej skomplikowanych formularzy przysparza on więcej problemów niż korzyści i szybciej bym zrealizował zakładaną funkcjonalność korzystając tylko z czystego HTML-a i logiki zawartej w kontrolerze.
Go to the top of the page
+Quote Post
ohm
post
Post #6





Grupa: Zarejestrowani
Postów: 623
Pomógł: 144
Dołączył: 22.12.2010

Ostrzeżenie: (0%)
-----


Cytat(mundeck @ 20.04.2017, 17:59:29 ) *
Tymczasem jednak mam spory problem - dość skomplikowany formularz, który działał dobrze, dopóki nie wziąłem się za walidację. Jedne jego części (embedded forms) są wyświetlane lub nie w zależności od opcji wybranych we wcześniejszych polach (steruje tym jquery), tak samo niektóre dalsze pola są włączane i wyłączane w zależności od wyboru. Myślałem, że jeśli wyłącze pola tej składowej formularza, która jest chowana to ominę walidację, ale tak się nie dzieje. W efekcie schowana część formularza jest walidowana i formularz nie przechodzi, bo nic tam nie było wpisane.


A korzystasz z form eventsów?

Cytat(mundeck @ 20.04.2017, 17:59:29 ) *
Szczerze mówiąc mam wrażenie, że o ile dla prostych formularzy typu "zapisz notkę na blogu" komponent Form działa prosto, intuicyjnie i szybko można go ogarnąć, o tyle dla bardziej skomplikowanych formularzy przysparza on więcej problemów niż korzyści i szybciej bym zrealizował zakładaną funkcjonalność korzystając tylko z czystego HTML-a i logiki zawartej w kontrolerze.

Też kiedyś tak myślałem (IMG:style_emoticons/default/wink.gif) Ale z czasem przyszła praktyka i teraz się tworzy i waliduje mi się duuużo szybciej formularze niż miałbym dłubać je ręcznie.


Co do samego transformera z domyślną wartościa, to możesz rzucić jakimś kodem?
Go to the top of the page
+Quote Post
mundeck
post
Post #7





Grupa: Zarejestrowani
Postów: 43
Pomógł: 0
Dołączył: 2.09.2012

Ostrzeżenie: (0%)
-----



Na razie nie korzystam, ale czytam o nich, więc może jak przetestuję i się przekonam, to skorzystam (IMG:style_emoticons/default/wink.gif)

Zaciekawiła mnie propozycja Crozin-a, ale nie bardzo wiem, jak taka klasa miałaby wyglądać, bo jeśli miałaby pokrywać wszystkie pola danej tabeli to czym różniłaby się od encji? I potem trzeba by było dla każdego z pól wstawiać odpowiednie wartości z tej klasy formularzowej do encji? Trochę nie kumam tego pomysłu

Kolejne pytanie: jak mam jednocześnie używać walidacji i transformerów, skoro transformery działają wcześniej niż walidacja? Istotą walidacji jest przecież to, żeby sprawdzać poprawność tych danych, które wpisał użytkownik i poinformować go o błędzie, a walidacja w Symfony następuje po transformacji, czyli dane są już "jakby" poprawne?

Ten post edytował mundeck 20.04.2017, 17:19:08
Go to the top of the page
+Quote Post
Pilsener
post
Post #8





Grupa: Zarejestrowani
Postów: 1 590
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

Ostrzeżenie: (0%)
-----


Wg mnie już kiepskim pomysłem jest zapisywanie czegoś innego niż wprowadza użytkownik, takie coś prędzej czy później źle się kończy (trudno przewidzieć wszystkie możliwości).
Czemu nie zrobić tego w JS? Do tego walidator by wymusić konkretny format (jeden lub wiele). Jak JS nie da rady sformatować to krzywdy nie ma.
A jeśli już chcemy zmieniać dane w ten sposób to w Zend było coś takiego jak Filter (może jest jakiś bundle do Symfony), w Symfony jest Data Transformer - tylko to jest dobre, jeśli chcemy używać tego wiele razy. Dla jednorazowego wyjątku lepiej użyć Form Events.
Go to the top of the page
+Quote Post
Crozin
post
Post #9





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


1. Wykorzystywanie Doctrine'owskiej encji w formularzu jest o tyle złe, że nagle jedna klasa zaczyna być odpowiedzialna za wiele różnego rodzaju zadań - jedno to obsługa modelu bazodanowego, drugie to obsługa jakiegoś konkretnego formularza.
2. W przypadku encji dodatkowym niebezpieczeńtwem jest to, że nawet nieprawidłowy (z punktu widzenia waildacji) formularz zmienia właściwości encji, jeżeli gdzieś dalej będziesz przypadkiem ją aktualizować (w jakimś fragemncie niezwiązanym z samym formularzem) możesz się nieciekawie zaskoczyć.
3. Nie jesteś zmuszony korzystać z komponentu formularzy. To co potrzebujesz osiągnąć można zrobić przy jego pomocy (wspomniane form events). Jeśli jednak nie czusz się w jego ramach "na siłach" możesz sobie ręcznie wykonać obsługę takiego formularza posiłkując się np. komponentem od samej walidacji.
4. Pamiętaj, że "szybciej i łatwiej" bardzo często nie oznacza "najmniejszą ilością kodu". Utworzenie dodatkowej klasy, stricte pod reprezentację modelu formularza oraz kilka linijek na zmapowanie danych przy poprawnym wypełnieniu ów formularza to 5 minut roboty.
5. To, że klasa reprezentująca dane z formularza i klasa encji ma trochę pokrywających się pól nie sprawia, że są tożsame.
5.1. Klasa od formularza co najwyżej zawiera zapewne mały podzbiór pol encji. Na pewno nie dajesz w niej właściwości typu ID, zapewne nie wszystkie relacje można zmieniać w tym formularzu itp.
5.2. Obiekt danych z formularza nie jest w żaden sposób powiązany z EntityManagerem Doctrine'a. Nie jest przedmiotem cyklu jego pracy - tutaj patrz na punkt #2.
6. Jesteś pewien, że data transformers podpiąłeś w odpowiednim miejscu? http://symfony.com/doc/current/form/data_t...ew-transformers
7. Pomysł zaproponowany przez @Pilsener by wykorzystać JS również nie jest najgorszy. Przy czym niezgodziłbym się ze stwierdzeniem, że z DataTransformers nie możesz korzystać nawet przy jednorazowym użyciu.

Ten post edytował Crozin 24.04.2017, 17:44:10
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 24.08.2025 - 22:27