Symfony2 和 Doctrine2 :用两个实体填充表单(一个复杂的场景)

Posted

技术标签:

【中文标题】Symfony2 和 Doctrine2 :用两个实体填充表单(一个复杂的场景)【英文标题】:Symfony2 and Doctrine2 : populate form with two Entity (a complicated scenario) 【发布时间】:2012-11-02 01:18:35 【问题描述】:

我有 5 个实体:

用户, 人, 用户从属关系, PersonAffiliation 和 隶属关系

这是架构:

一些细节:

WebUser 是在网站上注册的人。对于每个 Webuser,都有一个个人 ID。

一个人可以是网络用户、作者等。

每个 WebUser 都有 0 个或多个从属关系。这些从属关系由该 WebUser 创建并链接到有能力的 UserAffiliations。

WebUser 还可以将他创建的从属关系链接到一个人(如果该人是作者),实体 PersonAffiliation 将被填充。

我现在正在尝试让网络用户可以将隶属关系分配给作者(人)。为此,我有:

在实体人中

@ORM\OneToMany(targetEntity="PersonAffiliation", mappedBy="person", cascade="persist", "remove")

protected $affiliations;

在 PersonAffiliation 中

@ORM\ManyToOne(targetEntity="Person", inversedBy="affiliations")
@ORM\JoinColumn(name="person_id", referencedColumnName="id")

protected $person;

@ORM\ManyToOne(targetEntity="Affiliation", inversedBy="person_affiliations")
@ORM\JoinColumn(name="affiliation_id", referencedColumnName="id")

protected $affiliation;

在实体用户中:

@ORM\OneToMany(targetEntity="UserAffiliation", mappedBy="user")

protected $affiliations;


@ORM\ManyToOne(targetEntity="Person")
@ORM\JoinColumn(name="person_id", referencedColumnName="id")

protected $person;

在实体UserAffiliation中

@ORM\ManyToOne(targetEntity="User", inversedBy="affiliations")
@ORM\JoinColumn(name="user_id", referencedColumnName="id")

protected $user;


@ORM\ManyToOne(targetEntity="Affiliation", inversedBy="user_affiliations")
@ORM\JoinColumn(name="affiliation_id", referencedColumnName="id")

 protected $affiliation;

在表格中,我在做下一步:

$builder->add('affiliations', 'entity', array(
            'class' => 'SciForumVersion2Bundle:PersonAffiliation',
            'query_builder' => function($em) use ($person)
            return $em->createQueryBuilder('pa')->where('pa.person_id = :id')->setParameter('id', $person->getId());
        ,
            'property'    => 'affiliation',
            'multiple' => true,
            'expanded' => true,
        ));

但是这一切都没有按照我的意愿正常工作。

说明:当我尝试添加新的从属关系时,它只是为 WebUser 添加的,我无法通过表单将其链接到作者(Person)。

您对如何解决这个问题有什么想法,或者有一个好的教程吗?

【问题讨论】:

您有 UserFormType 和嵌入式 PersonFormType 吗? @Cerad,我有一个 SubmissionAffiliationFormType 和一个 SubmissionAuthorFormType。 SubmissionAffiliationFormType 用于为特定用户创建新的附属关系,SubmissionAuthorFormType 用于将附属关系链接到特定人(作者)。 可能只有我一个人,但我不明白这个问题。 $person 来自哪里?始终是用户还是用户试图与另一个人建立联系?你有什么活动可以让我们点击查看问题吗?考虑到用户始终是人,拥有 UserAffliation 和 PersonAffliation 似乎是错误的。但这只是本能,反映了我对目标的不理解。 @Cerad,事实上,一个人可以是任何东西,一个用户、一个作者或者其他人。不同的是,用户是用来登录网站的(他是注册人)。用户有自己的从属关系,但也可以创建从属关系(这就是 UserAffiliations 表存在的原因)。当用户创建一个作者(另一个人)时,该用户可以为 htis 作者(人)分配从属关系,他可以创建新的从属关系或从表 UserAffiliations 中选择他创建的从属关系。我目前没有任何在线信息,但如果需要,可以提供有关问题的更多详细信息。 【参考方案1】:

这应该在Entity1Controller.php中处理:

public function createAction(Request $request)

  $securityContext = $this->get('security.context');
  $em = $this->getDoctrine()->getManager();
  $form = $this->createForm(new Entity1Type()
     ,null,array('attr' => array('securitycontext' => $securityContext)));
  $form->bind($request);

  if ($form->isValid())
    $data = $form->getData();
    $entity1id = $data->getId();
    $entity2id = $data->getEntity2Id();
    $entity1medicaid=$data->getMedicaidID();
    $entity1=$em->getRepostiory('projectBundle:Entity1')->findOneById($entity1id);
    $entity2=$em->getRepository('projectprojectBundle:Entity2')->findOneById($entity2id);
    if (null === $entity1)
      $entity1=new entity1();
      $entity1->setEntity2id($entity2id);
      $entity1->setID($entity1id);
    
    if (null === $entity2)
      $entity2=new entity2();
      $entity2->setID($entity2id);
    
    $em->persist($entity1);
    $em->persist($entity2);
    $em->flush();
    return $this->redirect($this->generateUrl('entity1', array()));
  

  return $this->render('Bundle:entity1:new.html.twig', array(
      'form'   => $form->createView()
     ,'attr' => array('securitycontext' => $securityContext
     )
  )
  );

您可能还必须在关联映射中设置级联持久性。 Entity1.yml:

project\projectBundle\Entity\Entity1:
    type: entity
    table: entity1
    repositoryClass: project\projectBundle\Entity\Entity1Repository
    fields:
        id:
            type: bigint
            id: true
            generator:
                strategy: AUTO
        property:
            type: string
            length: 255
            unique: true
    manyToMany:
        entity2:
            targetEntity: entity2
            mappedBy: entity1
            cascade: ["persist"]

理论上,symfony 将使 entity2 处于底层,从而使第二个 if null 子句变得不必要,但这总是困扰着我,所以我更喜欢明确地这样做。

【讨论】:

【参考方案2】:

如果这个表单将集合绑定到 WebUser 实体是因为你在 Controller 中将此类的对象传递给表单创建,这意味着:

$webUser = new WebUser();

$this->createForm(new SubmissionAffiliationFormType(), $webUser);

或者您通过不设置 DefaultOptions 并明确告诉它必须绑定到的 data_class 将使用哪个类的决定委托给 Symfony Forms:

class SubmissionAffiliationFormType extends AbstractType


    //...

    public function getDefaultOptions(array $options)
    
        return array(
            'data_class' => 'Acme\DemoBundle\Entity\Person',
        );
    

【讨论】:

以上是关于Symfony2 和 Doctrine2 :用两个实体填充表单(一个复杂的场景)的主要内容,如果未能解决你的问题,请参考以下文章

Symfony2 项目中的 Doctrine2 映射问题

使用 YAML 的 Doctrine2 和 Symfony2 的默认列值?

如何从 Symfony2 和 Doctrine2 中的一个点保存和检索纬度和经度

Doctrine2 自定义类型不像主键 Symfony2 那样工作

由 Doctrine2 (Symfony2) 生成的约束中的奇怪随机名称

Symfony2 Doctrine2 获取所有表