Я создаю новый объект и привязываю его к форме. Пользователь заполняет форму и переходит на страницу предварительного просмотра. Я храню ответы пользователя в сеансе.
Проблема возникает, когда я пытаюсь перезагрузить объект из сеанса, когда пользователь вернется, чтобы изменить форму. Я получаю, что сущности, переданные в поле выбора, должны управляться ошибкой.
У кого-нибудь есть идея, где я могу ошибиться? Вот код для контроллеров.
public function previewdealAction(Request $request){ $session = $this->getRequest()->getSession(); $coupon = $session->get('coupon'); $form = $this->createForm(new CouponType(), $coupon); if ($request->getMethod() == 'POST') { //bind the posted form values $form->bindRequest($request); //once a valid form is submitted ... if ($form->isValid()){ //Proceed to Previewing deal $file = $coupon->getImage(); $file->upload(); $session->set('coupon', $coupon); $repository = $this->getDoctrine() ->getRepository('FrontendUserBundle:Coupon'); $coupons = $repository->findAll(); return $this->render('FrontendHomeBundle:Merchant:dealpreview.html.twig', array('coupon'=>$coupon, 'coupons'=>$coupons)); } } } public function builddealAction(Request $request){ $em = $this->get('doctrine')->getEntityManager(); $user = $this->container->get('security.context')->getToken()->getUser(); //check for a coupon session variable $session = $this->getRequest()->getSession(); $coupon = $session->get('coupon'); //If coupon is not set if($coupon == NULL){ $coupon = new Coupon(); $date = new \DateTime(date("Ymd H:i:s")); $coupon->setStartdate($date); $coupon->setPosterid($user); $session->set('coupon', $coupon); } $form = $this->createForm(new CouponType(), $coupon); return $this->render('FrontendHomeBundle:Merchant:builddeal.html.twig', array( 'form' => $form->createView(), )); }
–
namespace Frontend\HomeBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; class CouponType extends AbstractType { public function buildForm(FormBuilder $builder, array $options) { $builder->add('couponname', 'text'); $builder->add('description', 'textarea'); $builder->add('price', 'money', array('currency' => 'USD')); $builder->add('originalprice', 'money', array('currency' => 'USD')); $builder->add('maxlimit', 'integer'); $builder->add('maxper', 'integer'); $builder->add('startdate', 'date', array( 'years' => array(2011, 2012, 2013, 2014), )); $builder->add('duration', 'choice', array( 'choices' => array( '3' => 3, '7' => 7, '14' => 14, '30' => 30, '60' => 60, '90' => 90, ), 'expanded' => false, 'multiple' => false, )); $builder->add('expirationdate', 'choice', array( 'choices' => array( '30' => 30, '60' => 60, '90' => 90, '180' => 180, ), 'expanded' => false, 'multiple' => false, )); $builder->add('tip', 'integer'); $builder->add('salestax', 'choice', array( 'choices' => array( 'included' => 'Sales tax is included and will be remitted BY YOU at the appropriate tax jurisdiction', 'exempt' => 'Sales tax is exempt according to seller\'s tax jurisdiction', 'collected' => 'Sales tax will be collected BY YOU at time of deal redemption', ), 'expanded' => true, 'multiple' => false, )); $builder->add('signature', 'text'); $builder->add('city', 'entity', array( 'class' => 'Frontend\\UserBundle\\Entity\\Cities', 'expanded' => false, 'multiple' => false, )); $builder->add('category', 'entity', array( 'class' => 'Frontend\\UserBundle\\Entity\\Category', 'expanded' => false, 'multiple' => false, )); $builder->add('address', new AddressType()); $builder->add('image', new DocumentType()); $builder->add('maxper', 'choice', array( 'choices' => array( '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9, '10' => 10, ), 'expanded' => false, 'multiple' => false, )); } public function getDefaultOptions(array $options) { return array( 'data_class' => 'Frontend\UserBundle\Entity\Coupon', ); } public function getName() { return 'user'; } }
heres класс типа купона
У меня возникла та же проблема: я извлекал данные из формы с помощью getData()
и сохранял в сеансе. Позже, после перенаправления, я пытался повторно заполнить другой экземпляр той же формы, используя setData()
.
У меня не было проблем с родными полями. Однако, когда моя форма включала сущность, я получал такое же страшное сообщение: «Сущности, переданные в поле выбора, должны управляться».
После того, как какая-то голова почесалась, проблема показала себя довольно простой (не все?). После перенаправления объект отделился; решение состоит в том, чтобы просто повторно включить объект в EntityManager, используя EntityManager::merge()
, тем самым восстановив объект как управляемый объект 🙂
// an array of form data from session $entity = $data['my_entity']; // merge() returns the managed entity $entity = $this->getDoctrine()->getEntityManager()->merge($entity); // update the form data array $data['my_entity'] = $entity; // Create form with form data $form = $this->createForm(new MyFormType(), $data);
http://www.doctrine-project.org/api/orm/2.0/doctrine/orm/entitymanager.html
Надеюсь это поможет!
Это не относится к решению вашей конкретной проблемы, но я хотел бы комментировать: у меня была такая же проблема, и я мог решить ее, удалив 'by_reference' => false
что было бесполезно здесь и причиной этой ошибки.
Имел ту же проблему и использовал в значительной степени ответ Дагга, но добавил небольшой цикл через массив сущностей, проверяя объекты:
if ($this->get('session')->has('filters')) { $filters = $this->get('session')->get('filters'); foreach ($filters as $key => $filter) { if (is_object($filter)) { $filters[$key] = $em->merge($filter); } } $filterForm = $this->createForm(new FilterType(), $filters); }
Надеюсь, это поможет кому-то.
У меня была та же проблема, и оба ответа были очень полезными, но моя проблема связана с многомерными массивами, чтобы поддерживать динамику. Я использовал рекурсивную версию функции jahller.
private function manageObjects(&$data_array) { foreach ($data_array as $key => &$value) if (is_object($value)) $data_array[$key] = $this->container->get('doctrine.orm.entity_manager')->merge($value); else if (is_array($value)) $this->manageObjects($value); }
Надеюсь, это поможет кому-то.
Более сложное решение на основе предыдущих комментариев. Поддержка объектов ArrayCollections и DateTime
/** * Merge objects * Allow to manage object by doctrine when using stored (eg. in session data values) * @param $data_array - list of form fields * @return mixed */ public function manageObjects($data_array) { foreach ($data_array as $key => $value) { // for multi choices if ($value instanceof ArrayCollection) { $data_array[$key] = $this->manageObjects($value); } //ommit dateTime object elseif ($value instanceof \DateTime) { } elseif (is_object($value)) { $data_array[$key] = $this->getService('doctrine.orm.entity_manager')->merge($value); } } return $data_array; }