Php ArrayCollection中嵌套的CollectionType保存实体

Php ArrayCollection中嵌套的CollectionType保存实体,php,doctrine-orm,symfony,Php,Doctrine Orm,Symfony,我想存储一些数据 class Offer { /** * @ORM\Column(type="array") */ private $meterPoints; public function __construct() { $this->meterPoints = new ArrayCollection(); } } 作为集合类型的报价 class OfferType extends AbstractType

我想存储一些数据

class Offer
{
    /**
     * @ORM\Column(type="array")
     */
    private $meterPoints;


    public function __construct()
    {
        $this->meterPoints = new ArrayCollection();
    }
}
作为集合类型的报价

class OfferType extends AbstractType
{
    $builder
        ->add('meterPoints', CollectionType::class, array(
            'entry_type' => OfferMeterPointType::class,
            'allow_add' => true,
            'allow_delete' => true,
            'prototype' => true,
            'prototype_name' => '__mp_name__',
        ))
}
在OfferMeterPointType中,我还有一个EntityType

class OfferMeterPointType extends AbstractType
{
    $builder
        ->add('meterPoint', EntityType::class, array(
            'attr' => array(
                'class' => 'chosen-select'
            ),
            'class' => 'AppBundle:MeterPoint',
            'choice_label' => 'meterPoint',
        ))
        ->add('billData', CollectionType::class, array(
            'label' => false,
            'entry_type' => OfferBillType::class,
            'allow_add' => true,
            'allow_delete' => true,
            'entry_options' => array(
                'label' => false
            )
        ));

}
现在,当我持久化该实体时,整个AppBundle:MeterPoint对象将被序列化,而不仅仅是id。我有点理解为什么doctrine会这样做,但是我可以更改它以便只存储id吗

当我想编辑报价时也是如此

$offer = $em->getRepository('AppBundle:Offer')->findOneById(2);
$form = $this->createForm(OfferType::class, $offer);
我有个例外

必须管理传递到选项字段的实体。也许可以将它们保存在实体管理器中

我想一个解决方案是为OfferTerPointType创建一个实体,但我真的不想这样做。因为我根本不需要这些数据

更新

我按照马丁的建议试过了。现在异常消失了,但它仍然保存完整的对象

$meterPoints = $this->em->getRepository('AppBundle:MeterPoint')->findAll();
    //dump($meterPoints);
    $builder
        ->add('meterPoint', ChoiceType::class, array(
            'label' => 'offerMeterPoint.meterPoint',
            'attr' => array(
                'class' => 'chosen-selesct',
                'placeholder' => 'ob.to'
            ),
            'choices' => $meterPoints,
            'choice_label' => function($meterPoint) {
                return $meterPoint->getMeterPoint();
            },
            'choice_value' => function($meterPoint) {
                if($meterPoint === null){
                    return null;
                }
                dump($meterPoint);
                return $meterPoint->getId();
            },
            'placeholder' => 'global.plz_select'
        ))
更新2 开始工作了 更改了选择类型

        $meterPoints = $this->em->getRepository('AppBundle:MeterPoint')->findAll();
    $mps = array();
    foreach($meterPoints as $mp){
        $mps [$mp->getMeterPoint()] = $mp->getId();
    }
    //dump($meterPoints);
    $builder
        ->add('meterPoint', ChoiceType::class, array(
            'label' => 'offerMeterPoint.meterPoint',
            'attr' => array(
                'class' => 'chosen-selesct',
                'placeholder' => 'ob.to'
            ),
            'choices' => $mps,
            'placeholder' => 'global.plz_select'
        ))
  • 由于列类型为
    array
    ,并且
    EntityType
    会自动用对象替换选择值,因此可以序列化对象

    不过,还有一个函数也接受callable,所以我会尝试处理它,也许你可以让它只返回id(可能是强制字符串类型?)

    如果这没有帮助,那么可能只使用
    选择type
    并自己处理逻辑

  • 发生这种情况的原因是,条令自动反序列化来自
    $meterPoints
    的对象,您尝试将这些对象用作具有
    EntityType
    的实体。这些对象显然不是由条令实体管理器管理的。这就是错误

    我认为如果您想避免创建更多关系,您必须在使用
    $this->createForm(…)
    之前将
    $meterPoints
    转换为数据库实体。最终,也许更简单的方法是编写一个定制的条令类型,可以为您做到这一点:

  • 由于列类型为
    array
    ,并且
    EntityType
    会自动用对象替换选择值,因此可以序列化对象

    不过,还有一个函数也接受callable,所以我会尝试处理它,也许你可以让它只返回id(可能是强制字符串类型?)

    如果这没有帮助,那么可能只使用
    选择type
    并自己处理逻辑

  • 发生这种情况的原因是,条令自动反序列化来自
    $meterPoints
    的对象,您尝试将这些对象用作具有
    EntityType
    的实体。这些对象显然不是由条令实体管理器管理的。这就是错误

    我认为如果您想避免创建更多关系,您必须在使用
    $this->createForm(…)
    之前将
    $meterPoints
    转换为数据库实体。最终,也许更简单的方法是编写一个定制的条令类型,可以为您做到这一点: