这是问题:

我有一个有 3 个类(class)的模型

  • person_job
  • 工作

  • 一个人可以有多个工作,任何工作-个人关系都可以有一个“date_start”属性、“date_end”和“comment”。所以我用一个可连接的 (person_job) 来构建这个模型,这个模型包含这些属性,并在 2 个 manyToOne 属性上建立关系,称为 person 和 job(用学说注释生成)

    人员属性如下所示:
    /**
    * @var string
    * @ORM\Column(name="name",type="string",length=255,nullable=false)
    */
    private $name;
    
    /**
    * @var string
    * @ORM\Column(name="firstname",type="string",length=255,nullable=true)
    */
    private $firstname;
    /**
    * @var bool
    * @ORM\Column(name="active", type="boolean")
    */
    private $active;
    

    作业属性如下所示:
    /**
    * @var string
    * @ORM\Column(name="name",type="string",length=255,nullable=false)
    */
    private $name;
    

    person_job 看起来像这样:
    /**
    * @ORM\ManyToOne(targetEntity="...\Person")
    * @ORM\JoinColumn(nullable=false)
    */
    private $person;
    
    /**
    * @ORM\ManyToOne(targetEntity="...\Job")
    * @ORM\JoinColumn(nullable=false)
    */
    private $job;
    
    /**
    * @var string
    * @ORM\Column(name="comment",type="string",length=255,nullable=true)
    */
    private $comment;
    
    /**
    * @var \DateTime
    * @ORM\Column(name="startdate",type="datetime")
    */
    private $datestart;
    
    /**
    * @var \DateTime
    * @ORM\Column(name="enddate",type="datetime")
    */
    private $dateend;
    

    现在我想为我的“人”构建一个表单,我可以在其中选择列表中的工作,并添加(如果需要)date_start、date_end 或与此工作相关的评论。我的 FormBuilder 对于 "Person"看起来像这样:
    $builder
      ->add('name')
      ->add('firstname')
      ->add('jobs',Job::class,array('label'=>'Job'));
    

    这失败了。我的 Person 类没有“jobs”属性。那么,我怎样才能做到这样的事情呢?我是否必须添加一个工作属性,上面有一个 oneToMany 关系,用“mappedBy”声明?

    这些学说中的关系仍然让我感到困惑,我是 symfony 的新手,我在互联网上查看,但还没有找到合适的解决方案/示例...

    感谢阅读/帮助

    最佳答案

    您遇到了 Symfony 表单中最困难的问题之一。幸运的是,有一些很好的文档。让我总结一下重要的步骤。

    你是对的:如果你想从 Person 的角度操纵这种关系,那么实体 Person 需要知道它与 PersonJob 的关系。所以你需要添加一个属性:

    // src/AppBundle/Entity/Person.php
    /**
     * @ORM\OneToMany(targetEntity="PersonJob", mappedBy="person")
     */
    private $personJobs;
    
    public function __construct()
    {
        $this->personJobs = new \Doctrine\Common\Collections\ArrayCollection();
    }
    

    然后你将拥有表单类型
    // src/AppBundle/Form/PersonType.php
    $builder
        ->add('name')
        ->add('firstname')
        ->add('personJobs', CollectionType::class, array(
            'entry_type'   => PersonJobType::class,
            'allow_add' => true,
        )
    ;
    

    注意 personJobs 字段的类型。由于一个人可以拥有多个 PersonJobs,因此您需要一种可以处理集合的表单类型。这是内置 CollectionType 的目的(查看 its documentation! )。您还需要表单类型 PersonJobType ,以便 CollectionType 知道如何构建子表单:
    class PersonJobType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('comment')
                ->add('datestart', DateTimeType::class)
                ->add('dateend', DateTimeType::class)
                ->add('job') // requires Job::__toString() to be defined!
            ;
        }
    
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'AppBundle\Entity\PersonJob'
            ));
        }
    }
    

    出于调试目的,请将您的 Controller 更改为
     public function testAction()
     {
        $person = new Person();
        $form = $this->createForm(PersonType::class, $person);
        $form->add('submit', SubmitType::class);
    
        $form->handleRequest($request);
    
        if ($form->isSubmitted() && $form->isValid()) {
            print '<pre>';
            var_dump($form->getData());
            die();
        }
    
        return $this->render('default/index.html.twig', [
            'form' => $form->createView(),
        ]);
    }
    

    现在继续从 Adding and Removing Items 复制并粘贴 Twig 和 Javascript 代码(您必须进行一些小的更改,例如将 form.emails 替换为 form.personJobs )。

    表格

    表格看起来像

    只是带有“添加另一个 PersonJob”链接的 Person 表单:

    php - 带有属性的一对多对一表单与 Symfony 3/Doctrine-LMLPHP

    添加一个 PersonJob:

    php - 带有属性的一对多对一表单与 Symfony 3/Doctrine-LMLPHP

    添加另一个 PersonJob:

    php - 带有属性的一对多对一表单与 Symfony 3/Doctrine-LMLPHP

    收到的数据

    提交表单并查看 var_dump 的输出:
    object(AppBundle\Entity\Person)#247 (5) {
      ["id":"AppBundle\Entity\Person":private]=>
      NULL
      ["name":"AppBundle\Entity\Person":private]=>
      string(12) "Charles Dude"
      ["firstName":"AppBundle\Entity\Person":private]=>
      string(7) "Charles"
      ["active":"AppBundle\Entity\Person":private]=>
      bool(true)
      ["personJobs":"AppBundle\Entity\Person":private]=>
      object(Doctrine\Common\Collections\ArrayCollection)#248 (1) {
        ["elements":"Doctrine\Common\Collections\ArrayCollection":private]=>
        array(2) {
          [0]=>
          object(AppBundle\Entity\PersonJob)#962 (6) {
            ["id":"AppBundle\Entity\PersonJob":private]=>
            NULL
            ["comment":"AppBundle\Entity\PersonJob":private]=>
            string(19) "Something important"
            ["datestart":"AppBundle\Entity\PersonJob":private]=>
            object(DateTime)#1088 (3) { … }
            ["dateend": …] => …
            ["person":"AppBundle\Entity\PersonJob":private]=>
            NULL
            ["job":"AppBundle\Entity\PersonJob":private]=>
            object(AppBundle\Entity\Job)#1171 (2) {
              ["id":"AppBundle\Entity\Job":private]=>
              int(2)
              ["name":"AppBundle\Entity\Job":private]=>
              string(5) "Job 2"
            }
          }
          [1]=> …
      }
    }
    

    还需要做两件事:
  • 将嵌套的 person 实体的 PersonJob 属性正确设置为新(但尚未持久化)的 Person。
  • 通过调用 PersonJob 来告诉 Doctrine 关于新的 $em->persist(…) 实体。

  • 相关文档:
  • CollectionType Field
  • How to Embed a Collection of Forms
  • 关于php - 带有属性的一对多对一表单与 Symfony 3/Doctrine,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38048806/

    10-09 07:37
    查看更多