【问题标题】:Entities passed to the choice field must be managed必须管理传递给选择字段的实体
【发布时间】:2011-09-19 16:02:35
【问题描述】:

我创建一个新对象并将其绑定到一个表单。用户填写表格并转到预览页面。我将用户响应存储在会话中。

当用户返回编辑表单时,当我尝试从会话中重新加载对象时,问题就出现了。我明白了:

错误:必须管理传递给选择字段的实体。

有人知道我哪里可能出错了吗?这是控制器的代码。

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\'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';
}

}

这里是优惠券类型类

【问题讨论】:

  • 你能添加你的 CouponType 类吗?
  • 优惠券和分类有什么关系?
  • max per 只是优惠券实体中的一个整数字段。
  • 主要的违规字段似乎是城市和类别。但这很奇怪,如果我从会话中加载优惠券实体,它只会引发错误,而不是如果它是新的 Coupon();
  • 你找到解决方案了吗?我正在使用FormBuilder::setData() 遇到类似的问题,我已从已发布的表单中提取并存储在会话中。

标签: php symfony


【解决方案1】:

我遇到了同样的问题 - 我正在使用 getData() 从表单中检索数据并存储在会话中。后来,在重定向之后,我尝试使用setData() 重新填充同一表单的另一个实例。

我在原生字段方面没有遇到任何问题。但是,当我的表单包含一个实体时,我收到了同样可怕的消息“必须管理传递给选择字段的实体”。

经过一番摸索后,问题变得非常简单(不是全部吗?)。重定向后,实体已分离;解决方案是使用EntityManager::merge() 将实体重新包含到EntityManager 中,从而将实体恢复为托管对象:)

// 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

希望这会有所帮助!

【讨论】:

  • 这真的很有帮助!非常感谢。
  • 这是一个巨大的帮助,解决了我在会话中存储实体的问题。我通过尝试使用选定值填充 formType 中的字段来通过“无法从选择列表中读取选择”(目前 Google 上的结果为 0)收到此错误 - 希望此评论将帮助其他人找到此答案。跨度>
  • 我有类似的问题 - 将数据保存在简单缓存中时 - 这解决了它!只需要小心并实际执行$agent = $em->merge($agent); 之类的操作,而不仅仅是$em->merge($agent);。谢谢!
  • 虽然 - 当你需要做太多的重新合并到 EM 中时,缓存的意义就丢失了,因为它太慢了。
  • 谢谢,虽然合并功能现在已弃用,但仍然有效。
【解决方案2】:

这与解决您的具体问题无关,但我想注释: 我遇到了同样的问题,可以通过删除 'by_reference' => false 来解决,这在此处是不必要的,也是出现此错误的原因。

【讨论】:

  • 谢谢。我急切地将'by_reference' => false 添加到我所有的关系中。然而,只有集合才真正需要这个。
【解决方案3】:

遇到了同样的问题,几乎使用了 Daggah 假设的答案,但在实体数组中添加了一个小循环,检查对象:

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);
}

希望这对某人有所帮助。

【讨论】:

  • 非常感谢,我在我的 arrayCollection 中使用了循环,它运行良好!
  • 优秀!!!如果 $filters 不是数组而是对象,只需将 $filters[$key] 第 5 行替换为 filter->$key(您的密钥必须是公开的)
  • 工作正常,除了 DateTime 对象,得到错误The class 'DateTime' was not found in the chain configured namespaces 知道为什么吗?
【解决方案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);
}

希望这对某人有所帮助。

【讨论】:

  • 递归函数似乎不起作用,它给了我: Class Doctrine\Common\Collections\ArrayCollection 不是有效的实体或映射的超类。但是,如果我像这里一样手动执行此操作:pastie.org/private/h082ucbyw6sz7dyym3avtq 它可以工作。
【解决方案5】:

基于 prev cmets 的更复杂的解决方案。 支持 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-14
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多