Symfony2,表单中包含实体类型

时间:2015-03-28 14:29:40

标签: symfony doctrine-orm symfony-forms

这是情况,我有一个表格,我需要一个实体字段类型。在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实体中项目的引用)。

你会注意到另一个领域,即福利子项,这与手头的问题无关。

据我所知,从Doctrine的角度来看,我必须设置一对多,单向连接表。

这两个实体是:

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

您还会注意到另一个实体,即BenefitItem,它是&#34;父亲&#34;福利集团。

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

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * @ORM\Entity()
 * @ORM\Table(name="benefit_group_category")
 * @UniqueEntity(fields={"name", "project"}, ignoreNull=false, message="Duplicated group category for this project")
 */
class BenefitGroupCategory
{
/**
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
 * @ORM\Column(type="string", length=50)
 */
protected $name;
/**
 * @ORM\ManyToOne(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 
"AppBundle\Entity\BenefitGroup".

&#34;美女&#34;即使我在&#34; isValid&#34;中评论(讨厌的)部分也是它的行为完全相同

我输了:(

1 个答案:

答案 0 :(得分:0)

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

编辑:

是的,但PHP只做浅拷贝,你必须克隆其他对象。查看示例#1克隆http://php.net/manual/en/language.oop5.cloning.php中的对象。您必须通过定义__clone方法克隆您的对象(对于Doctrine低于2.0.2,您必须通过在克隆后调用自己的方法来执行此操作,因为代理定义了它自己的__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);
   }
}