Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [SF][SF2][Symfony2] Walidacja danych wysłanych z niestandardowego forma., Manualne tworzenie formularza i jego obsługa
damianooo
post 25.03.2016, 08:43:35
Post #1





Grupa: Zarejestrowani
Postów: 496
Pomógł: 2
Dołączył: 15.07.2011
Skąd: Katowice

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


Witam,

Jak zwalidować w akcji kontrolera dane wyslane z formularza utworzonego manualnie ?

Moj formularz w TWIG:
  1. <form action="{{ path('typerka_types') }}" method="post">
  2. <div class="coupon_form">
  3. {% for key,match in matches %}
  4. <input type="hidden" name="match_id[]" value="{{ match.match_id }}">
  5. <div class="coupon_form_host">
  6. {{ match.host }}
  7. </div>
  8. <div class="coupon_form_host_type">
  9. <input type="text" name="hostType[]">
  10. </div>
  11. <div class="coupon_form_guest_type">
  12. <input type="text" name="guestType[]">
  13. </div>
  14. {% endfor %}
  15. </div>
  16. <input type="submit" value="Submit">
  17. </form>


Kontroler:

  1. public function typesAction(Request $request){
  2.  
  3. $repository = $this->getDoctrine()->getRepository('MyTyperkaBundle:Match');
  4. $matches = $repository->getMatchesPerMatchday(1);
  5.  
  6. if ($request->getMethod() == 'POST') {
  7. $req = $request->request->all();
  8. // ...
  9. $type = new Type();
  10. $match = new Match();
  11. // ....
  12. $em->persist($match);
  13. $em->persist($type);
  14. $em->flush();
  15. }
  16.  
  17. return $this->redirect($this->generateUrl('typerka_types'));
  18. }
  19. return array('matches' => $matches);


Normalnie robi sie to tak :

  1. $form->handleRequest($Request);
  2. if($form->isValid()){



ale u siebie mnie nie tworze forma w kontrolerze.





Go to the top of the page
+Quote Post
uirapuru
post 25.03.2016, 09:15:23
Post #2





Grupa: Zarejestrowani
Postów: 182
Pomógł: 9
Dołączył: 30.04.2005

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


jeżeli chcesz zwalidować dane, to uzyj po prostu walidatora na wynikowym (przesłanym) obiekcie. walidator to osobny komponent symfony i może działać bez formularza. musiałbyś jednak dorobić i powielić sporo istniejącej już funkcjonalności m.in. do spopulowania obiektu danymi wejściowymi. Osobiście dla kazdych danych wejściowych (nie ważne, czy pochodzących od uzytkownika, czy automatycznego klienta) staram się tworzyć formularz - czytaj to jako funkcjonalność, a nie rezultat wizualny (formularz można, ale nie trzeba wyrenderować "do widoku"). na Twoim miejscu więc wysiliłbym się i stworzył klase formularza, nawet jeżeli jego pola sa tworzone dynamicznie, to z pewnościa jest jakiś algorytm jego tworzenia smile.gif następnie skorzystał z $form->isValid() jak biały człowiek smile.gif

Ten post edytował uirapuru 25.03.2016, 09:16:19
Go to the top of the page
+Quote Post
damianooo
post 25.03.2016, 09:34:48
Post #3





Grupa: Zarejestrowani
Postów: 496
Pomógł: 2
Dołączył: 15.07.2011
Skąd: Katowice

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


ehh ... no to mnie zmartwiłeś smile.gif ...

Chciałem to zrobić jak "biały człowiek" jednak miałem problem z uzyskaniem tego co potrzebowałem zrobić, a wiec:
- pobrać dane w RepositoryClass
- wyswietlić je w Twig
- dodać do tych danych pola do wypełnienia
- zapisać dane z wypełnionych pol w bazie

Ten post edytował damianooo 25.03.2016, 09:36:26
Go to the top of the page
+Quote Post
uirapuru
post 25.03.2016, 09:38:54
Post #4





Grupa: Zarejestrowani
Postów: 182
Pomógł: 9
Dołączył: 30.04.2005

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


do tego co mi sie wydaje, potrzebujesz połączyć dwie rzeczy: embedded collection oraz dynamical forms. pierwsze pozwoli Ci stworzyć podformularze dla każdej encji z kolekcji (u Ciebie chyba matches), a eventy do dynamicznego tworzenia pól jeżeli masz tam odrobinę więcej logiki potrzebnej
Go to the top of the page
+Quote Post
damianooo
post 25.03.2016, 09:54:26
Post #5





Grupa: Zarejestrowani
Postów: 496
Pomógł: 2
Dołączył: 15.07.2011
Skąd: Katowice

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


ok chyba nie bede mial wyjscia i powinienem to zrobic jak "bialy czlowiek" ... i rozumiem ze najlepiej zawsze isc ta droga w Symfony ....

Podpowiedz mi tylko czy powinienem tego forma i embeded collection robic dla encji Type czy Match ?
PS. Encja Type to ta ktorej dane bede dodawal do bazy, natomiast encja Match to ta, ktorej dane chce tylko wyswietlic w Twigu i nic wiecej z nimi nie robic.

W takiej relacji jest encja Type z encja Match:

  1. /**
  2.   * @ORM\ManyToOne(
  3.   * targetEntity = "Match",
  4.   * )
  5.   *
  6.   * @ORM\JoinColumn(
  7.   * name = "match_id",
  8.   * referencedColumnName = "id",
  9.   * onDelete = "SET NULL"
  10.   * )
  11.   */
  12. private $match;



Go to the top of the page
+Quote Post
Pyton_000
post 25.03.2016, 10:16:34
Post #6





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Przepraszam że się wpie... między wódkę a zakonskę ale zawsze mnie mnie dziwi dlaczego w Symfony/Zend to musi być takie skomplikowane. Każda pierdoła która powinna być zrobiona na maksa prosto bez udziwnień musi być zrealizowana przy pomocy pierdylardu klas, metod, tricków, hacków wink.gif

Go to the top of the page
+Quote Post
uirapuru
post 25.03.2016, 10:30:35
Post #7





Grupa: Zarejestrowani
Postów: 182
Pomógł: 9
Dołączył: 30.04.2005

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


to nie jest kwestia symfony, tylko zasad dobrego programowania. spaghetti możesz tworzyć w kazdym fw, w symfony również smile.gif

@damianooo:

stwórz formularz osobiście do sprawy podchodze tak, że:

- moje encje nie maja setterów, parametry podaję do konstruktora tylko przy utworzeniu, wymusza to tworzenie metod z logiką, które sprawiają, że encja nie jest "anemiczna"
- tworzę sobie klase formularza opartą o klasę DTO
- tworzę sobie prostą klasę DTO, którą wpinam w formularz; zawiera ona publiczne pola np. kolekcje itd (wiem, ze DTO nie powinno zawierac encji, tylko id's ale w moich przypadkach jest to pomijalne - nie serializuję dto i nie pcham po api)
- tworzę serwis implementujący konkretną ścieżkę działania (przypadek użycia), zapodaje jej wszystkie potrzebne zależności i w jego metodzie handle zawieram logikę - utworzenie, obrobienie i zapis do bazy. oczywiście TDD, więc mam od razu otestowany kod; na koniec działania rzucam event, że działanie wykonane lub exception
- tworzę sobie factory dla encji (jedna dla match i druga dla type), dzięki temu mam w systemie jedno centralne miejsce, gdzie encje są tworzone i nigdzie indziej nie ma czegoś takiego jak new Match itp; robie w niej metodę createEntityFromCommand, która DTO konwertuje do encji
- w kontrolerze: tworzę formularz, wciskam w niego DTO, populuje DTO requestem, robię walidację DTO a nie encji (trzymam jej zasady w validation.yml), jesli valid to na utworzonym serwisie robię po prostu ->handle($command), przekazuje formularz do widoku i np. ustawiam flash dla usera.

voila. wszystko odizolowane i otestowane, a ten sam kod moge wykorzystać na stronie, w api czy commandzie bez różnicy.

  1. /**
  2.   * @Route("/rejestracja.html", name="evento_register")
  3.   * @Template()
  4.   */
  5. public function registerAction(Request $request)
  6. {
  7. $response = new Response(null, 200);
  8. $createCommand = new CreateWorkshop();
  9. $createCommand->lessons = [new CreateLesson()];
  10. $form = $this->createForm("register_workshops_form_type", $createCommand, [
  11. "action" => $this->generateUrl("evento_register"),
  12. "method" => "POST",
  13. ]);
  14. if($request->isMethod("POST"))
  15. {
  16. $form->handleRequest($request);
  17. if($form->isValid())
  18. {
  19. $this->get("tactician.commandbus")->handle($form->getData());
  20. $this->addFlash("success", "Dziękujemy za dodanie nowej informacji, po weryfikacji przez moderatora pojawi się w bazie");
  21. return $this->redirectToRoute("evento_homepage");
  22. } else {
  23. $response->setStatusCode(400);
  24. }
  25. }
  26. return $this->render("AppBundle:Default:register.html.twig", [
  27. "form" => $form->createView(),
  28. ], $response);
  29. }


Jak chcesz sobie podejrzeć, to mam taką tu małą appkę, nie zastosowałem wydzielenia klas domeny i aplikacji ani TDD ze względu na wielkość, ale to chyba identyczny przypadek jak Twoj - formularz z jedną kolekcją

https://github.com/uirapuru/evento/tree/master/src/AppBundle

Ten post edytował uirapuru 25.03.2016, 10:32:30
Go to the top of the page
+Quote Post
damianooo
post 25.03.2016, 11:10:22
Post #8





Grupa: Zarejestrowani
Postów: 496
Pomógł: 2
Dołączył: 15.07.2011
Skąd: Katowice

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


to co piszesz to troche wyzsza szkola jazdy wiec pewnie tym razem niestety nie skorzystam bo niestety nie umiem jeszcze tyle ...
bede chcial jednak to zrobic oczywiscie tak jak zasugerowales a wiec z wykorzystniem standardowego formularza ...
i na pewno uproscic jak sie da ... mam nadzieje ze w moim problemie, ktory mam do rozwiazania to mi sie uda ...
podziałam i podziele sie rozwiazaniem tutaj na forum ...
Go to the top of the page
+Quote Post
uirapuru
post 25.03.2016, 11:19:41
Post #9





Grupa: Zarejestrowani
Postów: 182
Pomógł: 9
Dołączył: 30.04.2005

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


nie mam ambicji bycia nauczycielem, ale myślę, że kazdy moment na naukę dobry, tymbardziej, że jeśli dobrze rozumiem dałem Ci przykład ze swojego kodu 1:1 z Twoim przypadkiem wink.gif mam nadzieję, że pomogłem.
Go to the top of the page
+Quote Post
damianooo
post 25.03.2016, 11:37:19
Post #10





Grupa: Zarejestrowani
Postów: 496
Pomógł: 2
Dołączył: 15.07.2011
Skąd: Katowice

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


hmm ... mowisz ze mamy podobienstwo 1:1 ... moze ... nie widze tego na razie

Zrobilem tak w kontrolerze:

  1. public function typesAction(Request $request){
  2.  
  3. $form = $this->createForm(new TypeType(), new Type(), array(
  4. 'action' => $this->generateUrl('typerka_types'),
  5. 'method' => 'POST',
  6. ));
  7. $form->add('submit', 'submit');
  8. $form->handleRequest($request);
  9. if ($request->getMethod() == 'POST') {
  10. if ($form->isValid()) {}
  11. }
  12. // ...


Formularz encji Type:

  1. public function buildForm(FormBuilderInterface $builder, array $options)
  2. {
  3. $builder
  4. ->add('hostType' )
  5. ->add('guestType' )
  6. ;
  7. }


niestety potrzebuje jeszcze pobrac dane z encji Match z Repository class:

  1. public function getMatchesPerMatchday($matchday){
  2. $qb = $this->createQueryBuilder('m');
  3. $qb->select(
  4. 'm.id AS match_id'
  5. ,'tm1.name AS host'
  6. ,'tm2.name AS guest'
  7. ,'m.description'
  8. ,'m.term'
  9. )
  10. ->innerJoin('m.hostTeam', 'tm1')
  11. ->innerJoin('m.guestTeam', 'tm2')
  12. ->innerJoin('m.matchday', 'md')
  13. ->where('md.id = :matchday')
  14. ->orderBy('m.id')
  15. ->setParameter('matchday', $matchday)
  16. ;
  17. // ...
  18. }


nie wiem jak to wszystko powiazac ...
Go to the top of the page
+Quote Post

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

 



RSS Wersja Lo-Fi Aktualny czas: 20.06.2025 - 13:06