表单中具有实体类型的Symfony2

表单中具有实体类型的Symfony2,symfony,doctrine-orm,symfony-forms,Symfony,Doctrine Orm,Symfony Forms,在这种情况下,我有一个表单,其中需要一个实体字段类型。在BenefitGroup实体中,我有一个BenefitGroupCategory选项 我的表格是: public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('BenefitGroupCategories', 'entity', array( 'class' => 'Ap

在这种情况下,我有一个表单,其中需要一个实体字段类型。在BenefitGroup实体中,我有一个BenefitGroupCategory选项

我的表格是:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('BenefitGroupCategories', 'entity', array(
                'class' => 'AppBundle:BenefitGroupCategory',
                'property' => 'name',
                'label' => false,
                'query_builder' => function(EntityRepository $er) {
                    return $er->createQueryBuilder('c')
                    ->orderBy('c.name', 'ASC');
                },))
            ->add('benefitsubitems', 'collection', array('type' => new BenefitSubItemFormType(), 'allow_add'    => true, 'label' => false,));

}
这几乎是一种典型的产品类别关系。一个利益集团只能有一个类别,而一个类别可以属于多个利益集团唯一的复杂性,尚未实现,但这就是我需要查询生成器的原因,因为所有这些都将依赖于另一个参数项目,因此某些类别将始终是默认的,其他项目仅适用于特定项目,请参见下面的BenefitGroupCategory实体中的项目参考

您将注意到另一个字段benefitsubitems,它与当前问题无关

据我所知,从理论的角度来看,我必须建立一个一对多、单向的with Join表

这两个实体是:

<?php
// src/AppBundle/Entity/BenefitGroup.php

namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="AppBundle\Entity\BenefitGroupRepository")
 * @ORM\Table(name="benefit_groups")
 */
class BenefitGroup
{
/**
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
 * @ORM\ManyToOne(targetEntity="BenefitItem", cascade={"persist"}, inversedBy="BenefitGroups")
 */
protected $benefitItem;

/**
 * @ORM\oneToMany(targetEntity="BenefitSubItem", mappedBy="benefitGroup")
 */    
protected $BenefitSubItems;


/**
 * @ORM\ManyToMany(targetEntity="BenefitGroupCategory")
 * @ORM\JoinTable(name="BenefitGroup_BenefitGroupCategory", joinColumns={@ORM\JoinColumn(name="BenefitGroup_id", referencedColumnName="id")}, inverseJoinColumns={@ORM\JoinColumn(name="BenefitGroupCategory_id", referencedColumnName="id", unique=true)})
 */    
protected $BenefitGroupCategories;

// HERE I HAVE SOME IRRELEVANT GETTERS AND SETTERS    

/**
 * Constructor
 */
public function __construct()
{
    $this->BenefitSubItems = new ArrayCollection();
    $this->BenefitGroupCategories = new ArrayCollection();
}

/**
 * Add BenefitGroupCategories
 *
 * @param \AppBundle\Entity\BenefitGroupCategory $benefitGroupCategories
 * @return BenefitGroup
 */
public function addBenefitGroupCategory(\AppBundle\Entity\BenefitGroupCategory $benefitGroupCategories)
{
    $this->BenefitGroupCategories[] = $benefitGroupCategories;

    return $this;
}

/**
 * Remove BenefitGroupCategories
 *
 * @param \AppBundle\Entity\BenefitGroupCategory $benefitGroupCategories
 */
public function removeBenefitGroupCategory(\AppBundle\Entity\BenefitGroupCategory $benefitGroupCategories)
{
    $this->BenefitGroupCategories->removeElement($benefitGroupCategories);
}

/**
 * Get BenefitGroupCategories
 *
 * @return \Doctrine\Common\Collections\Collection 
 */
public function getBenefitGroupCategories()
{
    return $this->BenefitGroupCategories;
}
}
问题是:在可视化中,它正确地可视化了表单,即使它没有正确地检索类别。我有一个类别的选择,这是可以的,但它没有检索到正确的一个。我必须在表单中设置默认值吗

当我使用表单创建一个新实体时,问题变得更加严重。请注意带有所有嵌套实体的克隆。问题是它说:

Neither the property "BenefitGroupCategories" nor one of the methods
"addBenefitGroupCategory()"/"removeBenefitGroupCategory()", 
"setBenefitGroupCategories()", "benefitGroupCategories()", "__set()" or 
"__call()" exist and have public access in class 
"AppBundle\Entity\BenefitGroup".
美妙之处在于,即使我完整地评论了文章中令人讨厌的部分,它的行为也完全相同


我迷路了:

关于克隆您必须取消设置克隆实体的id,请看这里:

编辑:

是的,但是PHP只是做浅层复制,你必须克隆其他对象。请看示例1在中克隆对象。您必须通过为低于2.0的条令定义_clone method来克隆对象。2您必须在克隆后调用own method来完成此操作,因为代理定义了它自己的_clone method。例如:

function __clone() {
   $oldCollection = $this->collection;
   $this->collection = new ArrayCollection();
   foreach ($oldCollection as $oldElement) {
       $newElement = clone $oldElement;
       // additional actions for example setting this object to owning side
       $newElement->setParent($this);
       $this->collection->add($newElement);
   }
}

我很确定你不必这么做。这里有人建议我使用这种方法,它实际上非常有效。如果我删除了类别,但保留了所有其他的3级嵌入等。。。这一切都是可行的,它创建了一个更新版本的所有对象之间正确链接。我运行的是条令2.4.7。我确实创建了所有其他对象,这些对象分配给正确的实体。它起作用了。问题不在那里。实际上,我把代码精简到了几行,并检测到了失败的地方。在创建表单中,我还删除了克隆,以防万一,问题仍然存在。翻开Symfony的文档,我发现我必须正确地实现getter。一种简单的方法是向addTag添加一些额外的逻辑,该逻辑由表单类型调用,因为by_引用设置为false:。我必须弄清楚在我的情况下该怎么办。我完全搞错了,我把实体类型当作一个集合。关于深度克隆,您是对的:出于一些模糊的原因,即级联持久化,所有实体都得到了正确的持久化。唯一引用原始实体的是实体类型,因此当我更新表单中的类别时,它会创建所有实体,但也会更改原始类别:。我们必须尝试实施你的建议。
Neither the property "BenefitGroupCategories" nor one of the methods
"addBenefitGroupCategory()"/"removeBenefitGroupCategory()", 
"setBenefitGroupCategories()", "benefitGroupCategories()", "__set()" or 
"__call()" exist and have public access in class 
"AppBundle\Entity\BenefitGroup".
function __clone() {
   $oldCollection = $this->collection;
   $this->collection = new ArrayCollection();
   foreach ($oldCollection as $oldElement) {
       $newElement = clone $oldElement;
       // additional actions for example setting this object to owning side
       $newElement->setParent($this);
       $this->collection->add($newElement);
   }
}