簡體   English   中英

具有屬性的一對多對一表格與Symfony 3 / Doctrine

[英]One-to-Many-to-One with attributes Form with Symfony 3 / Doctrine

這是問題所在:

我有一個有3個班級的模型

  • person_job
  • 工作

一個人可以有多個工作,任何工作人員關系都可以有“date_start”屬性,“date_end”和“comment”。 所以我用一個包含這些屬性的jointable(person_job)構建了這個模型,並在2個manyToOne屬性上創建了一個名為person和job的關系(用doctrine注釋生成)

人物屬性如下:

/**
* @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關系的jobs屬性,並使用“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的目的(查看其文檔! )。 您還需要表單類型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'
        ));
    }
}

出於調試目的,將控制器更改為

 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(),
    ]);
}

現在繼續復制和粘貼,從樹枝和JavaScript代碼, 添加和刪除項目 (你必須做出細微的變化,如更換form.emailsform.personJobs )。

表格

表格看起來像

只是帶有“添加另一個PersonJob”鏈接的Person表單:

第一步

添加PersonJob:

添加PersonJob

添加anothing PersonJob:

添加另一個PersonJob

收到的數據

提交表單並查看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]=> …
  }
}

還有兩件事要做:

  1. 將嵌套的PersonJob實體的person屬性正確設置為新的(但尚未PersonJob )Person。

  2. 通過在它們上面調用$em->persist(…) PersonJob $em->persist(…)來告訴Doctrine有關新PersonJob實體的信息。

相關文件:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM