PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Um-para-muitos-para-um com atributos Form com Symfony 3 / Doctrine


Você se deparou com um dos problemas mais difíceis com os formulários do Symfony. Felizmente, existe uma boa documentação. Deixe-me resumir os passos importantes.

Você está certo:a entidade Person precisa saber sobre seu relacionamento com PersonJob se você quiser manipular esse relacionamento do ponto de vista de uma pessoa. Então você precisa adicionar uma propriedade:
// src/AppBundle/Entity/Person.php
/**
 * @ORM\OneToMany(targetEntity="PersonJob", mappedBy="person")
 */
private $personJobs;

public function __construct()
{
    $this->personJobs = new \Doctrine\Common\Collections\ArrayCollection();
}

e então você terá no tipo de formulário
// src/AppBundle/Form/PersonType.php
$builder
    ->add('name')
    ->add('firstname')
    ->add('personJobs', CollectionType::class, array(
        'entry_type'   => PersonJobType::class,
        'allow_add' => true,
    )
;

Observe o tipo de personJobs campo. Como uma pessoa pode ter muitos PersonJobs, você precisa de um tipo de formulário que possa lidar com coleções. Este é o propósito do CollectionType integrado (confira sua documentação! ). Você também precisa do tipo de formulário PersonJobType , para que CollectionType sabe como construir os sub-formulários:
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'
        ));
    }
}

Para fins de depuração, altere seu controlador para
 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(),
    ]);
}

Agora vá em frente e copie e cole o código Twig e Javascript de Adicionando e removendo itens (você precisa fazer pequenas alterações, como substituir form.emails com form.personJobs ).

O formulário


O formulário ficará como

Apenas o formulário Person com um "Adicionar outro PersonJob" link:



Adicionando um PersonJob:



Adicionando outro PersonJob:


Os dados recebidos


Envie o formulário e veja a saída de 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]=> …
  }
}

Duas coisas ainda precisam ser feitas:

  1. Defina a person propriedade do PersonJob aninhado entidades adequadamente para a nova (mas ainda não persistente) Pessoa.

  2. Conte ao Doctrine sobre o novo PersonJob entidades chamando $em->persist(…) neles.

Documentação relevante: