表单中具有实体类型的Symfony2



这是一种情况,我有一个表单,其中需要一个实体字段类型。在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,));
}

这几乎是一种典型的产品类别关系。一个BenefitGroup只能有一个类别,一个类别可以属于许多BenefitGroups(唯一的复杂性,尚未实现,但这就是我需要查询生成器的原因,因为所有这些都将取决于另一个参数(项目),因此一些类别将是默认类别(始终可用),其他项目将仅适用于特定项目(见下文BenefitGroupCategory实体中的项目参考)。

您会注意到另一个字段benefitsitems,它与手头的问题无关。

据我所知,从条令的角度来看,我必须建立一个一对多、单向的联接表。

这两个实体是:

<?php
// src/AppBundle/Entity/BenefitGroup.php
namespace AppBundleEntity;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineORMMapping as ORM;
/**
 * @ORMEntity(repositoryClass="AppBundleEntityBenefitGroupRepository")
 * @ORMTable(name="benefit_groups")
 */
class BenefitGroup
{
/**
 * @ORMColumn(type="integer")
 * @ORMId
 * @ORMGeneratedValue(strategy="AUTO")
 */
protected $id;
/**
 * @ORMManyToOne(targetEntity="BenefitItem", cascade={"persist"}, inversedBy="BenefitGroups")
 */
protected $benefitItem;
/**
 * @ORMoneToMany(targetEntity="BenefitSubItem", mappedBy="benefitGroup")
 */    
protected $BenefitSubItems;

/**
 * @ORMManyToMany(targetEntity="BenefitGroupCategory")
 * @ORMJoinTable(name="BenefitGroup_BenefitGroupCategory", joinColumns={@ORMJoinColumn(name="BenefitGroup_id", referencedColumnName="id")}, inverseJoinColumns={@ORMJoinColumn(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 AppBundleEntityBenefitGroupCategory $benefitGroupCategories
 * @return BenefitGroup
 */
public function addBenefitGroupCategory(AppBundleEntityBenefitGroupCategory $benefitGroupCategories)
{
    $this->BenefitGroupCategories[] = $benefitGroupCategories;
    return $this;
}
/**
 * Remove BenefitGroupCategories
 *
 * @param AppBundleEntityBenefitGroupCategory $benefitGroupCategories
 */
public function removeBenefitGroupCategory(AppBundleEntityBenefitGroupCategory $benefitGroupCategories)
{
    $this->BenefitGroupCategories->removeElement($benefitGroupCategories);
}
/**
 * Get BenefitGroupCategories
 *
 * @return DoctrineCommonCollectionsCollection 
 */
public function getBenefitGroupCategories()
{
    return $this->BenefitGroupCategories;
}
}

您还会注意到另一个实体BenefitItem,它是BenefitGroup的"父亲"。

<?php
// src/AppBundle/Entity/BenefitGroupCategory.php
namespace AppBundleEntity;
use DoctrineORMMapping as ORM;
use SymfonyBridgeDoctrineValidatorConstraintsUniqueEntity;
/**
 * @ORMEntity()
 * @ORMTable(name="benefit_group_category")
 * @UniqueEntity(fields={"name", "project"}, ignoreNull=false, message="Duplicated group category for this project")
 */
class BenefitGroupCategory
{
/**
 * @ORMColumn(type="integer")
 * @ORMId
 * @ORMGeneratedValue(strategy="AUTO")
 */
protected $id;
/**
 * @ORMColumn(type="string", length=50)
 */
protected $name;
/**
 * @ORMManyToOne(targetEntity="Project")
 */
protected $project;
// HERE I HAVE SOME IRRELEVANT GETTERS AND SETTERS    
}

在控制器中(你会看到几个嵌入的集合,它们工作正常)我有:

/**
 * @Route("/benefit/show/{projectID}", name="benefit_show")
 */
public function showAction(Request $request, $projectID)
{
    $id=4; //the Id of the CVC to look for
    $storedCVC = $this->getDoctrine()
                      ->getRepository('AppBundle:CVC')
                      ->find($id);
    $form = $this->createForm(new CVCFormType(), clone $storedCVC);
    $form->handleRequest($request);
    if ($form->isValid())
        {
        $em = $this->getDoctrine()->getManager();
        //$benefitGroupCategoryRepository = $this->getDoctrine()->getRepository('AppBundle:BenefitGroupCategory');
        $formCVC = $form->getData();
        $em->persist($formCVC);
        foreach ($formCVC->getBenefitItems() as $formBI)
            {
            $newBI = new BenefitItem();
            $newBI->setCVC($formCVC);
            $newBI->setComment($formBI->getComment());
            $em->persist($newBI);
            foreach ($formBI->getBenefitGroups() as $formBG)
                {
                $newBG = new BenefitGroup();
                $newBG->setBenefitItem($newBI);
                $newBG->setBenefitGroupCategories($formBG->getBenefitGroupCategories());
                $em->persist($newBG);
                foreach ($formBG->getBenefitSubItems() as $formSI)
                    {
                    $newSI = new BenefitSubItem();
                    $newSI->setBenefitGroup($newBG);
                    $newSI->setComment($formSI->getComment());
                    $em->persist($newSI);
                    }
                }
            }
            $em->flush();            
        }
    return $this->render('benefit/show.html.twig', array(
        'form' => $form->createView(),
    ));
}

问题是:在可视化中,它可以正确地可视化表单(即使它没有正确检索类别。我可以选择类别,这是可以的,但它没有检索到正确的类别。我必须在表单中设置默认值吗?

问题变得更糟当我汇总表单时,它应该创建一个带有所有嵌套实体的新实体(注意克隆)。问题是它崩溃了,说:

Neither the property "BenefitGroupCategories" nor one of the methods
"addBenefitGroupCategory()"/"removeBenefitGroupCategory()", 
"setBenefitGroupCategories()", "benefitGroupCategories()", "__set()" or 
"__call()" exist and have public access in class 
"AppBundleEntityBenefitGroup".

"美妙之处"在于,即使我完整地评论了"isValid"中的(讨厌的)部分,它的行为也完全相同

我迷路了:(

关于克隆,您必须取消设置克隆实体的id,请查看此处:https://stackoverflow.com/a/14158815/4723525

编辑:

是的,但PHP只是做浅层复制,你必须克隆其他对象。查看示例#1在中克隆对象http://php.net/manual/en/language.oop5.cloning.php.你必须通过定义__clone方法来克隆你的对象(对于低于2.0.2的Doctrine,你必须在克隆后调用自己的方法来克隆,因为代理定义了它自己的__clone方式)。例如:

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

相关内容

  • 没有找到相关文章

最新更新