Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [Symfony] Formularz z kolekcją ale trochę inaczej
JoShiMa
post 9.12.2017, 23:04:27
Post #1





Grupa: Zarejestrowani
Postów: 1 374
Pomógł: 149
Dołączył: 1.03.2006

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


Otóż mam taki problem. Z bazy pobieram informację o pewnej grupie użytkowników. Będę te informacje wyświetlać w tabeli. W jednym z pół tabeli ma się znaleźć niewielki TextArea za pomocą którego (via AJAX) zostanie do bazy dopisany komentarz dotyczący wybranego użytkownika.

I teraz tak. Wymyśliłam sobie, że cała tabelka powinna być formularzem a te pola TextArea powinny być kolekcją. Tylko jak zrobić, żeby indeksy odpowiadały ID usera. Czyli jesli w tabelce mam userów o id 5,12 i 17 to chcę miec tam pola

  1. <textarea id="form_comment_5" name="form[comment][5]" ></textarea>
  2. <textarea id="form_comment_12" name="form[comment][12]"></textarea>
  3. <textarea id="form_comment_17" name="form[comment][17]"></textarea>


A może to bez sensu robić to za pomocą FormBuildera skoro i tak będzie obsłużone AJAX-em?

Ten post edytował JoShiMa 9.12.2017, 23:05:00


--------------------
Go to the top of the page
+Quote Post
Pilsener
post 10.12.2017, 01:36:21
Post #2





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

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


Cytat
Wymyśliłam sobie, że cała tabelka powinna być formularzem a te pola TextArea powinny być kolekcją
- słabo, ponieważ formularze powinny jak najbardziej odpowiadać encjom. Im bardziej odejdziemy od struktury danych tym większe problemy w implementacji, formularze w symfony są zaprojektowane pod kątem współpracy z encjami.
Najprostsze rozwiązanie to dodanie formularza "UserForm" do wysyłanej do widoku kolekcji, np. tak:
  1. foreach($users as $userEntity){
  2. $userEntity->form = $this->createForm(UserForm::class, $userEntity);
  3. }

Potem wystarczy jedynie wyrenderować i jeśli mamy akcję do edycji usera via ajax to nie musimy już prawie nic robić poza podpięciem formularza do tej akcji.
Oczywiście trzeba wziąć pod uwagę takie rzeczy jak:
- csrf
- walidacja
- obsługa błędów
- edycja?
Jeśli dodanie formularza do każdego rekordu jest z jakiś powodów (np. wydajność) problematyczne, to można formularz wygenerować znów via ajax oddzielnie dla każdego rekordu.
Kolejna opcja to wygenerowanie formularza w JS na onclick bez żadnego requestu, jednak to wiąże się z dość dużym nakładem pracy i powoduje liczne problemy (np. z różnicami w renderowaniu pomiędzy PHP a JS).
I znów na ostatnim miejscu można to zrobić całkowicie ręcznie, jednak wtedy musimy implementować wszystko sami (np. walidację). Takie rozwiązanie polecałbym w ostateczności, bo często z jakiś powodów nie da się inaczej.
Go to the top of the page
+Quote Post
JoShiMa
post 10.12.2017, 11:18:59
Post #3





Grupa: Zarejestrowani
Postów: 1 374
Pomógł: 149
Dołączył: 1.03.2006

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


Powinnam generować cały formularz nawet jeśli potrzebuję z mienić w locie jedno pole (dodać komentarz do usera a w innym miejscu tj na innej podstronie zmienić wartość jakiegoś pola z 0 n 1)?


--------------------
Go to the top of the page
+Quote Post
Pilsener
post 10.12.2017, 18:39:39
Post #4





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

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


Generować w sensie, że renderować? Niezupełnie, nawet jeśli używamy formularza (np. UserForm), który zawiera wszystkie pola to definiujemy w nim opcję "mode", która może być np. "add", "edit", "comment" czy "changePassword", czyli parametryzujemy ten formularz. Formularz musi być zgodny z requestem, inaczej będą problemy z walidacją, nadmiarowymi polami czy też pozwolimy zmienić coś co nie powinno być zmienione.
Oczywiście jeśli logiki przybywa to formularz warto podzielić np. na oddzielne od edycji, dodawania czy komentowania - to już od nas zależy.
Go to the top of the page
+Quote Post
JoShiMa
post 10.12.2017, 23:13:44
Post #5





Grupa: Zarejestrowani
Postów: 1 374
Pomógł: 149
Dołączył: 1.03.2006

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


Dopiero się uczę. Jak wyrenderować poprawnie w widoku taki formularz podpięty do poszczególnych elementów kolekcji w sposób jaki pokazałeś w pierwszym poście?


kiedy próbuję renderować poszczególne formularze w pętli w szablonie dostaję komunikat:

Type error: Argument 1 passed to Symfony\Component\Form\FormRenderer::renderBlock() must be an instance of Symfony\Component\Form\FormView, null given, called in

  1. {% for item in newcooperations %}
  2. jakiś kod
  3. {{ form_start(item.form) }}
  4.  
  5. {{ form_end(item.form) }}
  6.  
  7. {% endfor %}


Ten post edytował JoShiMa 11.12.2017, 01:35:36


--------------------
Go to the top of the page
+Quote Post
Pilsener
post 11.12.2017, 12:37:26
Post #6





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

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


Trzeba sprawdzić:
  1. dump(item.form);


Z jakiś powodów jest null, a ma być FormView, który tworzymy z form poprzez proste wywołanie metody ->createView()
Go to the top of the page
+Quote Post
JoShiMa
post 12.12.2017, 04:12:49
Post #7





Grupa: Zarejestrowani
Postów: 1 374
Pomógł: 149
Dołączył: 1.03.2006

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


Rzeczywiście mój błąd. chciałabym Cię jeszcze poprosić o pomoc w jednej sprawie.

Mam dwie encje połączone taką relacją:

  1. class User extends BaseUser
  2. {
  3. ...
  4. /**
  5.   * @var Article[]|ArrayCollection
  6.   *
  7.   * @ORM\OneToMany(targetEntity="Cooperation", mappedBy="patient", cascade={"ALL"})
  8.   */
  9. private $therapists;
  10.  
  11. /**
  12.   * @var Article[]|ArrayCollection
  13.   *
  14.   * @ORM\OneToMany(targetEntity="Cooperation", mappedBy="therapist", cascade={"ALL"})
  15.   */
  16. private $patients;
  17. }
  18.  


  1. class Cooperation
  2. {
  3. /**
  4.   * @ORM\Id
  5.   * @ORM\ManyToOne(targetEntity="User", inversedBy="therapists")
  6.   * @ORM\JoinColumn(name="patient", referencedColumnName="id")
  7.   */
  8. private $patient;
  9.  
  10. /** @ORM\Id
  11.   * @ORM\ManyToOne(targetEntity="User", inversedBy="patients")
  12.   * @ORM\JoinColumn(name="therapist", referencedColumnName="id")
  13.   */
  14. private $therapist;
  15.  
  16. ...


Próbuję zrobić do tego pewien formularz.

Jeśli zrobię to tak:

  1. public function buildForm(FormBuilderInterface $builder, array $options)
  2. {
  3. $builder
  4. ->add('patient', HiddenType::class)
  5. ->add('therapist', HiddenType::class)
  6. ->add('comment', TextareaType::class, [
  7. 'label' => false,
  8. 'attr' => [
  9. 'class' => 'form-control add-comment',
  10. 'rows' => '4',
  11. 'cols' => '20',
  12. ],
  13. ]);
  14.  


to wtedy mam po wygenerowaniu formularza w tych polach mam w wartości 'username' zamiast 'id'. Jeśli taki formularz wyślę ajaxem to nijak nie umiem go zwalidować.


--------------------
Go to the top of the page
+Quote Post
Pilsener
post 12.12.2017, 11:04:59
Post #8





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

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


Jeśli w encji jest relacja to w formularzu pole powinno być np. EntityType. HiddenType można mapować string lub int. Jeśli potrzebujemy zamiast np. selecta wpisać id to trzeba skorzystać z data transformers:
https://symfony.com/doc/current/form/data_transformers.html
ale tak szczerze to lepiej tego unikać, bo to prawie niczego nie rozwiązuje a stwarza kolejne problemy. Zresztą pisałem już chyba o tym, że im bardziej formularz przypomina encję (lub jej część) tym lepiej.
I zawsze lepiej jest najpierw zrobić tradycyjnie, a dopiero gdy wszystko działa to podpinamy pod AJAX, modale etc.
Go to the top of the page
+Quote Post
JoShiMa
post 13.12.2017, 01:30:59
Post #9





Grupa: Zarejestrowani
Postów: 1 374
Pomógł: 149
Dołączył: 1.03.2006

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


Sądziłam, że EntityType służy wyłącznie do tworzenia pola wyboru :/

Rozwiązałam problem, ale połowicznie v konstrukcji formularza użyłam. property_path

  1. public function buildForm(FormBuilderInterface $builder, array $options)
  2. {
  3. $builder
  4. ->add('patient', HiddenType::class,['property_path'=>'patient.id'])
  5. ->add('therapist', HiddenType::class,['property_path'=>'patient.id'])
  6. ->add('comment', TextareaType::class, [
  7. 'label' => false,
  8. 'attr' => [
  9. 'class' => 'form-control add-comment',
  10. 'rows' => '4',
  11. 'cols' => '20',
  12. ],
  13. ]);


I to działa jeśli idzie o edycję encji. Jednak jesli chcę stworzyć encję i w tym celu wyprodukować pusty formularz:

  1. $cooperation = new Cooperation();
  2. $form = $this->createForm(CooperationType::class,$cooperation);


To dostaję błąd: PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path "patient.id" at property "id".

Co jest zrozumiałe, bo ne ma żadnego obiektu patient z którego możnaby pobrać id.


--------------------
Go to the top of the page
+Quote Post
Pilsener
post 13.12.2017, 09:23:31
Post #10





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

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


Zacząć należało od tego, czy naprawdę potrzebny jest w formularzu ten "terapist" i "patient"?
Bo nie rozumiem, czemu to mają być pola typu hidden a nie np. selecty czy radia gdzie użytkownik może wybrać?
I w tego typu problemach zazwyczaj trzeba albo sparametryzować formularz (by działał w trybie "add" lub "edit") albo stworzyć dwa oddzielne formularze.
Go to the top of the page
+Quote Post
JoShiMa
post 15.12.2017, 01:02:40
Post #11





Grupa: Zarejestrowani
Postów: 1 374
Pomógł: 149
Dołączył: 1.03.2006

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


Rzeczywiście ostatecznie po przemyśleniu okazało się, że te pola nie są potrzebne. Bo id user to id zalogowanego a id terapeuty to można przekazać w linku.


--------------------
Go to the top of the page
+Quote Post
StevDefs
post 28.08.2019, 00:57:31
Post #12





Grupa: Zarejestrowani
Postów: 51
Pomógł: 0
Dołączył: 22.08.2019

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


Purchasing Viagra Online For Cheap Propecia Generic Drug Pharmacy Gel Kamagra Francia priligy in sri lanka How Can I Get Viagra

Bentyl Tab Saturday Delivery Nursing Dogs And Amoxicillin Macrobid Saturday Delivery buy viagra online Bentyl Mastercard Canada Mixing Amoxicillin Wine Together Difference Between Amoxicillin And Penicillin

Walmart Propecia Price cheapest cialis Viagra Alle Donne Keflex And Stomach Bentyl Internet

Hydrochlorothiazide Best Website Keflex Recovery Acheter Du Cialis En Suisse generic cialis Wirkung Viagra 100mg

Dutasteride Vs Finasteride 2014 How To Last Longer During Why Discard Amoxil After Expire cialis overnight shipping from usa Photos De Pilules Amoxil
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: 17.11.2019 - 18:06