Объекты, переданные в поле выбора, должны управляться
Я создаю новый объект и привязываю его к форме. Пользователь заполняет форму и переходит на страницу предварительного просмотра. Я сохраняю ответы пользователя в сеансе.
Проблема возникает, когда я пытаюсь перезагрузить объект из сеанса, когда пользователь вернется, чтобы изменить форму. Я получаю, что сущности, переданные в поле выбора, должны управляться ошибкой.
У кого-нибудь есть идея, где я могу ошибиться? Вот код для контроллеров.
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("Y-m-d 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\ 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 класс типа купона
Ответы
Ответ 1
У меня возникла та же проблема: я извлекал данные из формы с помощью 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
Надеюсь, это поможет!
Ответ 2
Это не относится к решению вашей конкретной проблемы, но я хотел бы комментировать:
У меня была такая же проблема, и я смог решить ее с помощью удаления 'by_reference' => false
, которая была бесполезной здесь и причиной этой ошибки.
Ответ 3
Имел ту же проблему и использовал в значительной степени ответ, который предположил Дагга, но добавил небольшой цикл через массив сущностей, проверяя объекты:
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);
}
Надеюсь, это поможет кому-то.
Ответ 4
У меня была одна и та же проблема, и оба ответа были очень полезны, но моя проблема связана с многомерными массивами, чтобы поддерживать динамику. Я использовал рекурсивную версию функции 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);
}
Надеюсь, это поможет кому-то.
Ответ 5
Более сложное решение на основе предыдущих комментариев.
Поддержка объектов 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;
}