Symfony ManyToMany双向关系仅在一个方向上持续存在

时间:2013-03-02 12:02:07

标签: symfony doctrine many-to-many bidirectional formbuilder

经过长时间在网上搜索,我决定自己写第一篇文章。   我希望我能以正确的方式做到这一点。

这是我的问题。   我在我的项目中使用symfony 2.1。   而且我必须处理两个物体之间的双向关系   我创建了2个实体,完成了映射,完成了控制器,模板和formBuilder。   我设法坚持两个实体。   对于一个实体,我可以坚持实体和与另一个实体的关系。   但对于另一个实体,我只能坚持实体。   与其他实体的关系不会持续存在。

以下是2个实体的摘录:

class EntrainementCategorie{
{...}

/**  @ORM\ManyToMany(targetEntity="EntrainementType", mappedBy="categories", cascade="persist") */
protected $types;

}

这是第二个实体:

class EntrainementType{

{...}

/** 
 * @ORM\ManyToMany(targetEntity="EntrainementCategorie",inversedBy="types", cascade="persist") 
 * @ORM\JoinTable(name="mottet_entrainement_types_categories",
 *                  joinColumns={@ORM\JoinColumn(name="idType", referencedColumnName="id")},
 *                  inverseJoinColumns={@ORM\JoinColumn(name="idCategorie", referencedColumnName="id")})
 */
protected $categories;

}

所以你可以看到,类别和类型之间存在双向多对多关系。

以下是控制器:

class EntrainementCategorieController extends GenericController{

{...}

public function creerAction(Request $request){
    return $this->creerActionGeneric($request,new Categorie(),new CategorieType());
}

}

第二个:

class EntrainementTypeController extends GenericController{

{...}   

public function creerAction(Request $request){
    return $this->creerActionGeneric($request,new Type(),new TypeType());
}

}

这是GenericController:

class GenericController extends Controller{

{...}

protected function creerActionGeneric(Request $request,$object,$objectType){
    $form = $this->createForm($objectType,$object);
    $isThereProblem = false;
    if ($request->isMethod('POST')) {
        $isThereProblem = true;
        $form->bind($request);
        if ($form->isValid()) {
            $this->getEntityManager()->persist($object);
            $this->getEntityManager()->flush();
            $this->get('session')->getFlashBag()->add('information', $this->FORM_SUCCESS_MESSAGE);
            $isThereProblem = false;
        }
    }
    if ($isThereProblem){
        $this->get('session')->getFlashBag()->add('error', $this->FORM_ERROR_MESSAGE);
    }
    return $this->render($this->BUNDLE.':'.$this->ENTITY.':'.$this->CREATE_TEMPLATE, array('form' => $form->createView()));
}

}

以下是formBuilder:

class EntrainementCategorieType extends AbstractType{

{...}

public function buildForm(FormBuilderInterface $builder, array $options){
    $builder->add('label','text')
            ->add('types','entity',array(
                                    'class' => 'KarateEntrainementBundle:EntrainementType',
                                    'property' => 'label',
                                    'multiple' => true,
                                    'expanded' => true));
}

}

第二个:

class EntrainementTypeType extends AbstractType{

{...}

public function buildForm(FormBuilderInterface $builder, array $options){
    $builder->add('label','text')
            ->add('categories','entity',array(
                                            'class' => 'KarateEntrainementBundle:EntrainementCategorie',
                                            'property' => 'label',
                                            'multiple' => true,
                                            'expanded' => true));
}

} 

因此,当我填充EntrainementType表单时,类型及其与类别的关系都是持久的。 但是当我填写EntrainementCategory表单时,只保留类别,而不是它与类型的关系。

有谁知道我做错了什么?

希望我已经清楚了。 谢谢你的帮助 !

2 个答案:

答案 0 :(得分:1)

我终于设法做到了。 我不能在那个上使用creerActionGeneric。 我必须明确设置类别和每种类型之间的关联:

$form->bind($request);
if ($form->isValid()) {
   $this->getEntityManager()->persist($categorie);
   foreach($categorie->getTypes() as $type){
      $type->addCategorie($categorie);
      $this->getEntityManager()->persist($type);
   }
   $this->getEntityManager()->flush();
}

这工作得很好。 但是我不知道为什么在另一个方向上,当我坚持从类型,我不必这样做? OO

答案 1 :(得分:0)

通过关系的学说配置,有更好的方法。 Doctrine将允许您指定引用关系的连接表和列。

我实际上偶然发现了这个答案,然后决定多读一遍,因为这似乎不合适......这是正确的方式来建立这样的关系(和在yml,因为这是我喜欢的),显然与我的实体(饲料可以拥有/属于许多列表和列表可以拥有/属于许多饲料)

Feed的配置:

manyToMany:
    providerLists:
        targetEntity: ProviderList
        joinTable:
            name: providerlist_feed
            joinColumns:
                feed_id:
                    referencedColumnName: id
            inverseJoinColumns:
                providerlist_id:
                    referencedColumnName: id

列表配置

manyToMany:
    feeds:
        targetEntity: Feed
        joinTable:
            name: providerlist_feed
            joinColumns:
                providerlist_id:
                    referencedColumnName: id
            inverseJoinColumns:
                feed_id:
                    referencedColumnName: id

因此,两个实体现在彼此拥有,并且两者将以相同的方式持续:)