Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][Symfony2] Problem z aktualizacją i dodawaniem kategorii
Forum PHP.pl > Forum > Przedszkole
peter13135
Stawiam pierwsze kroki we frameworku symfony2 i niemogę przeskoczyć problemu.
Mam 3 tabele :
questions (id, name, surname, email, question)
categories(id, name)
question_category(category_id, question_id).
Jak łatwo się domyśleć jest to relacja wiele do wielu.

Chcę zrobić aktualizację "questions". Zrobiłeem sobię kontroler :

  1. public function updateAction($id)
  2. {
  3. $request = Request::createFromGlobals();
  4. $question = $this->getDoctrine()->getRepository('AdmFormBundle:Question')->find($id);
  5. echo 'przed' . (count($question->categories));
  6. $form = $this->createForm(new QuestionType(), $question );
  7. if($request->getMethod() == 'POST')
  8. {
  9. $form->bindRequest($request);
  10. echo 'po' . (count($question->categories));
  11. if($form->isValid())
  12. {
  13. $em = $this->getDoctrine()->getEntityManager();
  14. $em->persist($question);
  15. $em->flush();
  16. $this->get('session')->setFlash('updated', $id);
  17. //return $this->redirect($this->generateUrl('question_get'));
  18. }
  19. }
  20. return array('form'=>$form->createView(), 'id'=>$id);
  21. }


Wyświetla on oczywiście formularz z polami (id, name, surname, email, question) oraz pole wielokrotnego wyboru kategorii.
Tutaj mój QuestionType :

  1.  
  2. class QuestionType extends AbstractType
  3. {
  4. public function buildForm(FormBuilder $builder, array $options)
  5. {
  6. $builder
  7. ->add('name', 'text', array('label'=>'Imię'))
  8. ->add('surname', 'text', array('label'=>'Nazwisko'))
  9. ->add('email', 'email', array('label'=>'E-mail'))
  10. ->add('question', 'textarea', array('label'=>'Pytanie'))
  11. ->add('categories', 'entity',
  12. array('label'=>'Kategorie',
  13. 'class' => 'AdmFormBundle:Category',
  14. 'multiple' => true,
  15. 'query_builder' => function($er)
  16. {
  17. return $er->createQueryBuilder('c')
  18. ->orderBy('c.id', 'ASC');
  19. }
  20.  
  21. ));
  22. }
  23.  
  24. public function getName()
  25. {
  26. return 'questionForm';
  27. }
  28.  
  29. }


Jak widzicie, do kontrolera dodałem 2 linjki kodu :
  1. echo 'przed' . (count($question->categories));

oraz
  1. echo 'po' . (count($question->categories));

Pierwsza wyświetla ilośc kategorii przed wysłaniem formularza, druga wyświetla ilość kategorii po wysłaniu formularza.
To działa prawidło. Wchodzę sobię w edycję "question" która jest przyporządkowana do jednej kategorii i wyświetla się "przed1".
Zaznaczam jeszcze jedną kategorię (czyli w swoim polu wielokrotnego wyboru mam już zaznaczone dwie opcje) kilkam submit i pod linijką "przed1" wyświetla się "po2".
Jednak W bazie danych nic się nie zmienia, zapytanie update wykonuję się tylko do tabeli questions. Do tabeli question_category nic się nie dodaje.

Moje pytanie : gdzie mam szukać błędu ?
Jakie pliki ewentualnie wam wkleić, by ułatwić wam pomoc dla mnie ? smile.gif
Crozin
Powinieneś ustawić by Doctrine automatycznie zapisywał obiekty z relacji categories zapisując obiekt Question. Zrobisz to przy pomocy parametru cascade dla adnotacji @ManyToMany.

PS. Po co tworzysz nowy obiekt Request, skoro istnieje już jeden w systemie. Z poziomu kontrolera możesz odwołać się do niego przez metodę Controller::getRequest().
peter13135
Dodałem, ale nic to nie zmieniło. Czy możesz rzucić na to okiem ?
  1. <?php
  2. namespace Adm\FormBundle\Entity;
  3.  
  4. use Doctrine\ORM\Mapping as ORM ;
  5. use Symfony\Component\Validator\Constraints as Assert;
  6. use Doctrine\Common\Collections\ArrayCollection;
  7. /**
  8.  *@ORM\Entity
  9.  *@ORM\Table(name="category")
  10. */
  11. class Category
  12. {
  13. /**
  14.   * @var ArrayCollection $questions
  15.   *
  16.   * @ORM\ManyToMany(targetEntity="Adm\FormBundle\Entity\Question", inversedBy="categories", cascade={"persist"} )
  17.   * @ORM\JoinTable(name="question_category")
  18.   */
  19. protected $questions;
  20.  
  21. /**
  22.   *@ORM\Id
  23.   *@ORM\Column(type="integer")
  24.   *@ORM\GeneratedValue(strategy="AUTO")
  25.   */
  26. protected $id;
  27.  
  28.  
  29. /**
  30.   *@ORM\Column(type="string", length=30)
  31.   *@Assert\NotBlank()
  32.   *@Assert\MinLength(
  33.   * limit=3,
  34.   * message="Your name must have at least 3 characters."
  35.   * )
  36.   */
  37. protected $name;
  38.  
  39.  
  40.  
  41. public function __construct()
  42. {
  43. $this->questions = new ArrayCollection();
  44. }
  45.  
  46.  
  47. /**
  48.   * Get id
  49.   *
  50.   * @return integer
  51.   */
  52. public function getId()
  53. {
  54. return $this->id;
  55. }
  56.  
  57. /**
  58.   * Set name
  59.   *
  60.   * @param string $name
  61.   */
  62. public function setName($name)
  63. {
  64. $this->name = $name;
  65. }
  66.  
  67. /**
  68.   * Get name
  69.   *
  70.   * @return string
  71.   */
  72. public function getName()
  73. {
  74. return $this->name;
  75. }
  76.  
  77. public function setQuestions($questions)
  78. {
  79. $this->questions = $questions ;
  80. }
  81. /**
  82.   * Get questions
  83.   *
  84.   * @return Doctrine\Common\Collections\Collection
  85.   */
  86. public function getQuestions()
  87. {
  88. return $this->questions;
  89. }
  90.  
  91. /**
  92.   * Add questions
  93.   *
  94.   * @param Adm\FormBundle\Entity\Question $questions
  95.   */
  96. public function addQuestion(\Adm\FormBundle\Entity\Question $questions)
  97. {
  98. $this->questions[] = $questions;
  99. }
  100.  
  101. public function __toString()
  102. {
  103. return $this->getName();
  104. }
  105. }



  1. <?php
  2. //src/Adm/FormBundle/Entity/Question.php
  3.  
  4. namespace Adm\FormBundle\Entity;
  5.  
  6. use Doctrine\ORM\Mapping as ORM ;
  7. use Symfony\Component\Validator\Constraints as Assert;
  8. use Doctrine\Common\Collections\ArrayCollection;
  9.  
  10. /**
  11.  *@ORM\Entity
  12.  *@ORM\Table(name="question")
  13. */
  14.  
  15. class Question
  16. {
  17.  
  18. /**
  19.   * @var ArrayCollection $categories
  20.   *
  21.   * @ORM\ManyToMany(targetEntity="Adm\FormBundle\Entity\Category", mappedBy="questions", cascade={"persist"})
  22.   * @ORM\JoinTable(name="question_category")
  23.   */
  24. protected $categories;
  25.  
  26.  
  27. /**
  28.   *@ORM\Id
  29.   *@ORM\Column(type="integer")
  30.   *@ORM\GeneratedValue(strategy="AUTO")
  31.   */
  32. protected $id;
  33.  
  34. /**
  35.   *@ORM\Column(type="string", length=30)
  36.   *@Assert\NotBlank()
  37.   * @Assert\MinLength(
  38.   * limit=3,
  39.   * message="Your name must have at least 3 characters."
  40.   * )
  41.   */
  42. protected $name;
  43. /**
  44.   *@ORM\Column(type="string", length=30)
  45.   * @Assert\MinLength(
  46.   * limit=3,
  47.   * message="Your name must have at least 3 characters."
  48.   * )
  49.   */
  50. protected $surname;
  51.  
  52. /**
  53.   *@ORM\Column(type="string", length=30)
  54.   */
  55. protected $email;
  56. /**
  57.   *@ORM\Column(type="datetime")
  58.   */
  59. protected $datetime ;
  60. /**
  61.   *@ORM\Column(type="text")
  62.   */
  63. protected $question;
  64.  
  65.  
  66. /**
  67.   * Set id
  68.   *
  69.   * @param integer $id
  70.   */
  71. public function setId($id)
  72. {
  73. $this->id = $id;
  74. }
  75.  
  76. /**
  77.   * Get id
  78.   *
  79.   * @return integer
  80.   */
  81. public function getId()
  82. {
  83. return $this->id;
  84. }
  85.  
  86. /**
  87.   * Set name
  88.   *
  89.   * @param string $name
  90.   */
  91. public function setName($name)
  92. {
  93. $this->name = $name;
  94. }
  95.  
  96. /**
  97.   * Get name
  98.   *
  99.   * @return string
  100.   */
  101. public function getName()
  102. {
  103. return $this->name;
  104. }
  105.  
  106. /**
  107.   * Set surname
  108.   *
  109.   * @param string $surname
  110.   */
  111. public function setSurname($surname)
  112. {
  113. $this->surname = $surname;
  114. }
  115.  
  116. /**
  117.   * Get surname
  118.   *
  119.   * @return string
  120.   */
  121. public function getSurname()
  122. {
  123. return $this->surname;
  124. }
  125.  
  126. /**
  127.   * Set email
  128.   *
  129.   * @param string $email
  130.   */
  131. public function setEmail($email)
  132. {
  133. $this->email = $email;
  134. }
  135.  
  136. /**
  137.   * Get email
  138.   *
  139.   * @return string
  140.   */
  141. public function getEmail()
  142. {
  143. return $this->email;
  144. }
  145.  
  146. /**
  147.   * Set datetime
  148.   *
  149.   * @param datetime $datetime
  150.   */
  151. public function setDatetime($datetime)
  152. {
  153. $this->datetime = $datetime;
  154. }
  155.  
  156. /**
  157.   * Get datetime
  158.   *
  159.   * @return datetime
  160.   */
  161. public function getDatetime()
  162. {
  163. return $this->datetime;
  164. }
  165.  
  166. /**
  167.   * Set question
  168.   *
  169.   * @param text $question
  170.   */
  171. public function setQuestion($question)
  172. {
  173. $this->question = $question;
  174. }
  175.  
  176. /**
  177.   * Get question
  178.   *
  179.   * @return text
  180.   */
  181. public function getQuestion()
  182. {
  183. return ($this->question);
  184. }
  185.  
  186. public function __construct()
  187. {
  188. $this->datetime = new \DateTime();
  189. $this->categories = new ArrayCollection();
  190. }
  191.  
  192.  
  193.  
  194. /**
  195.   * Add categories
  196.   *
  197.   * @param Adm\FormBundle\Entity\Category $categories
  198.   */
  199. public function addCategory(\Adm\FormBundle\Entity\Category $categories)
  200. {
  201. $this->categories[] = $categories;
  202. }
  203.  
  204. /**
  205.   * Get categories
  206.   *
  207.   * @return Doctrine\Common\Collections\Collection
  208.   */
  209. public function getCategories()
  210. {
  211. return $this->categories;
  212. }
  213.  
  214.  
  215. public function setCategories($categories)
  216. {
  217. $this->categories = $categories;
  218. }
  219. public function __toString()
  220. {
  221. return $this->getName();
  222. }
  223.  
  224. }


Może tu coś skopałem. Praca na tych doctrinowych obiektach nie jest dla mnie oczywista.
Crozin
Teraz wydaje się to być w porządku.
1. Czy obiekt $question posiada poprawne dane, w momencie kiedy go zapisujesz?
2. Czy ręczne zapisanie obiektu (nie poprzez Symfony'owy framework formularzy) również nie działa?
peter13135
1.Sprawdzam w ten sposób :
  1. echo $question->getName()

albo
  1. $cat = $question->getCategories();
  2. echo $cat[0]->getName();

I wyświetla się to co w formularzu wpisałem.
2.
  1. public function updateAction($id)
  2. {
  3. $request = Request::createFromGlobals();
  4. $question = $this->getDoctrine()->getRepository('AdmFormBundle:Question')->find($id);
  5. $form = $this->createForm(new QuestionType(), $question );
  6. if($request->getMethod() == 'POST')
  7. {
  8. $form->bindRequest($request);
  9. if($form->isValid())
  10. {
  11. $question->setName('hehe nana');
  12. $cat = new Category();
  13. $cat->setName('hehee');
  14. $question->addCategory($cat);
  15. $em = $this->getDoctrine()->getEntityManager();
  16. $em->persist($question);
  17. $em->flush();
  18. $this->get('session')->setFlash('updated', $id);
  19.  
  20. //return $this->redirect($this->generateUrl('question_get'));
  21. }
  22. }
  23. return array('form'=>$form->createView(), 'id'=>$id);
  24. }


Zrobiłem takie coś :
Kategoria się dodaje (do tabeli categories)
Ale nie dodaje się do question_categories :/

question->name ma wartość 'hehe nana' bez względu na to co wpiszę w formularzu.

Może podlinkować wam całego bundla?

Problem rozwiązany, tam gdzie było inversedBY dałem mappedBy i odwrotnie.
Może mi ktoś powiedzieć, dlaczego ta zamiana poskutkowała ?
Co to ma do rzeczy ? Przecież tabele są sobie równorzędne. Tak samo pytanie ma kategorię, jak i każda kategoria ma pytania.
Crozin
Tworząc relację wiele-do-wielu powinieneś tylko po jednej stronie ustawić @JoinTable. Dla tej strony relacji będzie inversedBy, dla drugiej mappedBy. Dla drugiej strony relacji ustawiasz już tylko @ManyToMany.
To którą stronę wybierzesz dla definicji @JoinTable jest bez znaczenia.
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.