Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Symfony2][Symfony] embedded form w FOSUserBundle
Forum PHP.pl > Forum > PHP > Frameworki
Foxx
Używam FOSUserBundle i chciałem rozszerzyć tabelę użytkownika o dodatkowe informacje. Ale ponieważ te informacje są różne dla różnych typów użytkowników to postanowiłem stworzyć osobne obiekty dla tych zestawów danych. A więc poza encją User.php mam też DoctorData.php. Wybrałem do tego relację dwukierunkową OneToOne.

Zainstalowałem FOSUserBundle i nadpisałem RegistrationController.php ponieważ chciałem rejestrującym użytkownikom nadawać odpowiednie uprawnienia. To wszystko się udało i działa. No i nadszedł czas, że chciałem osadzić formularz z dodatkowymi danymi w formularzu rejestracji. Udało mi się to tak, że widzę wszystkie pola naraz i przy zapisaniu formularza tworzy się w bazie obiekt User oraz obiekt DoctorData.

Problem: obiekt DoctorData ma pustą wartość w polu, które powinno przechowywać identyfikator rekordu User. Trochę już się z tym męczę i nie umiem znaleźć elementu, który przegapiam bo jednocześnie nie jestem jeszcze doświadczony w SF2 oraz mam tu do czynienia z "obcym" bundlem.

User.php (fragment dotyczący relacji):
  1. /**
  2.  * @ORM\Entity
  3.  * @ORM\Table(name="fos_user")
  4.  */
  5. class User extends BaseUser
  6. {
  7.  
  8. /**
  9.   * @ORM\Id
  10.   * @ORM\Column(type="integer")
  11.   * @ORM\GeneratedValue(strategy="AUTO")
  12.   */
  13. protected $id;
  14.  
  15. /**
  16.   * @ORM\OneToOne(targetEntity="DoctorData", mappedBy="fos_user", cascade={"remove","persist"})
  17.   **/
  18. protected $doctorData;

DoctorData.php (fragment dotyczący relacji):
  1. /**
  2.  * @ORM\Entity
  3.  * @ORM\Table(name="doctor_data")
  4.  */
  5. class DoctorData
  6. {
  7.  
  8. /**
  9.   * @ORM\Id
  10.   * @ORM\Column(type="integer")
  11.   * @ORM\GeneratedValue(strategy="AUTO")
  12.   */
  13. protected $id;
  14.  
  15. /**
  16.   * @ORM\OneToOne(targetEntity="User", inversedBy="doctor_data")
  17.   * @ORM\JoinColumn(name="fos_user_id", referencedColumnName="id")
  18.   */
  19. private $fos_user;

Osadzanie formularza (nadpisany formularz rejestracji):
  1. class RegistrationFormType extends BaseType
  2. {
  3. public function buildForm(FormBuilderInterface $builder, array $options)
  4. {
  5. parent::buildForm($builder, $options);
  6.  
  7. # Dołączam formularz danych lekarza (bo rejestrują się tylko lekarze)
  8. $builder->add('doctor_data', new DoctorDataType());
  9. }
  10.  
  11. public function setDefaultOptions(OptionsResolverInterface $resolver)
  12. {
  13. $resolver->setDefaults(array(
  14. 'data_class' => 'Doctors\UserBundle\Entity\User',
  15. 'intention' => 'registration',
  16. 'cascade_validation' => true,
  17. ));
  18. }
  19.  
  20.  
  21. public function getName()
  22. {
  23. return 'doctors_user_registration';
  24. }
  25. }

Akcja zapisująca formularz (nadpisany kontroler z FOSUserBundle):
  1. public function registerAction(Request $request)
  2. {
  3. /** @var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
  4. $formFactory = $this->container->get('fos_user.registration.form.factory');
  5. /** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */
  6. $userManager = $this->container->get('fos_user.user_manager');
  7. /** @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
  8. $dispatcher = $this->container->get('event_dispatcher');
  9.  
  10. $user = $userManager->createUser();
  11. $user->setEnabled(true);
  12.  
  13. $user->addRole('ROLE_DOCTOR'); // nadaję uprawnienia
  14.  
  15. $dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, new UserEvent($user, $request));
  16.  
  17. $form = $formFactory->createForm();
  18. $form->setData($user);
  19.  
  20. if ('POST' === $request->getMethod()) {
  21. $form->bind($request);
  22.  
  23. if ($form->isValid()) {
  24. $event = new FormEvent($form, $request);
  25. $dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
  26.  
  27. $userManager->updateUser($user);
  28.  
  29. if (null === $response = $event->getResponse()) {
  30. $url = $this->container->get('router')->generate('fos_user_registration_confirmed');
  31. $response = new RedirectResponse($url);
  32. }
  33.  
  34. $dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
  35.  
  36. return $response;
  37. }
  38. }
  39.  
  40. return $this->container->get('templating')->renderResponse('FOSUserBundle:Registration:register.html.'.$this->getEngine(), array(
  41. 'form' => $form->createView(),
  42. ));
  43. }


A więc byłbym wdzięczny za pomoc w odkrywaniu dlaczego w DoctorData nie zapisuje się ten identyfikator Usera. Oraz oczywiście za wskazanie innych błędów w rozumowaniu.
minolone
Witam.

Czy przypadkiem to nie jest ten błąd?
  1. inversedBy="doctor_data"

a w klasie User masz doctorData zamiast doctor_data ?

przy zapisie do bazy nie wyświetla się żaden błąd w app_dev.php?

Tutaj przykład Doctrine
Foxx
No tak, chyba miałeś rację z tym błędem, poprawiłem ale nadal nie przyniosło to efektu: zapisują się oba rekordy, w obu tabelach, ale DoctorData pole fos_user_id pozostaje puste. Poprawiłem (chyba?) te wartości pól, przegenerowałem encje i teraz klasy wyglądają tak:

  1. /**
  2.  * @ORM\Entity
  3.  * @ORM\Table(name="fos_user")
  4.  */
  5. class User extends BaseUser
  6. {
  7.  
  8. /**
  9.   * @ORM\Id
  10.   * @ORM\Column(type="integer")
  11.   * @ORM\GeneratedValue(strategy="AUTO")
  12.   */
  13. protected $id;
  14.  
  15. /**
  16.   * @ORM\OneToOne(targetEntity="DoctorData", mappedBy="fos_user", cascade={"remove","persist"})
  17.   **/
  18. private $doctor_data;
  19.  
  20. //...


  1. /**
  2.  * @ORM\Entity
  3.  * @ORM\Table(name="doctor_data")
  4.  */
  5. class DoctorData
  6. {
  7.  
  8. /**
  9.   * @ORM\Id
  10.   * @ORM\Column(type="integer")
  11.   * @ORM\GeneratedValue(strategy="AUTO")
  12.   */
  13. protected $id;
  14.  
  15. /**
  16.   * @ORM\OneToOne(targetEntity="User", inversedBy="doctor_data")
  17.   * @ORM\JoinColumn(name="fos_user_id", referencedColumnName="id")
  18.   */
  19. private $fos_user;
  20.  
  21. //...


Może chodzi o jakiś konflikt w nadanych nazwach tabel i tych pól, które są takie same? EDIT: sprawdziłem z innymi nazwami i nadal to samo.

A może potrzebna jest jeszcze jakaś zmiana w kontrolerze FOSUserBundle? No bo ja go nadpisałem, ale praktycznie nie zmieniłem i nie wiem czy nie trzeba zrobić czegoś żeby uwzględniał dołączony obiekt przy zapisie?

Nadałem parametr cascade={"remove","persist"} ale może to nie wystarczy?

Żadnego błędu nie ma w _dev, wszystko działa dobrze poza tym, że pole fos_user_id pozostaje puste.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.