Hello tous,

je travaille sur les formulaires imbriqués de symfony mais j'ai vraiment du mal même en suivant pas à pas le "cours sur symfony et les formulaires imbriqués"

J'ai toujours mon entité Opérations qui peut contenir des Ventilations :

Operation

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 
/**
 * @var ArrayCollection $ventilations
 *
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\Ventilation", mappedBy="operation", cascade={"persist"})
 */
protected $ventilations;
 
/**
 * Constructor
 */
public function __construct()
{
    $this->ventilations = new \Doctrine\Common\Collections\ArrayCollection();
}
 
/**
 * Add ventilation
 *
 * @param \AppBundle\Entity\Ventilation $ventilation
 *
 * @return Operation
 */
public function addVentilation(\AppBundle\Entity\Ventilation $ventilation)
{
    $ventilation->setOperation($this);
    this->ventilations[] = $ventilation;
 
    return $this;
}
 
/**
 * Remove ventilation
 *
 * @param \AppBundle\Entity\Ventilation $ventilation
 */
public function removeVentilation(\AppBundle\Entity\Ventilation $ventilation)
{
    $this->ventilations->removeElement($ventilation);
}
 
/**
 * Get ventilations
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getVentilations()
{
    return $this->ventilations;
}
Ventilation

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
/**
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Operation", inversedBy="ventilations")
 * @ORM\JoinColumn(name="operation_id", referencedColumnName="id", onDelete="CASCADE")
 */
protected $operation;
 
/**
 * Set operation
 *
 * @param \AppBundle\Entity\Operation $operation
 *
 * @return Ventilation
 */
public function setOperation(\AppBundle\Entity\Operation $operation = null)
{
    $this->operation = $operation;
 
    return $this;
}
 
/**
 * Get operation
 *
 * @return \AppBundle\Entity\Operation
 */
public function getOperation()
{
    return $this->operation;
}
Les formumaires sont définis comme ceci

OperationType

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 
<?php
 
namespace AppBundle\Form;
 
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use AppBundle\Form\VentilationType;
 
class OperationType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('libelle', TextType::class)
            ->add('date', DateType::class, array(
                'widget' => 'single_text',
                'format' => 'dd/MM/yyyy'))
            ->add('estPointe', CheckboxType::class, array(
                'required' => false,
            ))
            ->add('ventilations', CollectionType::class, array(
                'entry_type' => VentilationType::class,
                'allow_add'    => true,
                'allow_delete' => true
            ))
        ;
    }
 
    /**
    ** {@inheritdoc}
    **/
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefined(array('compte'));
    }
 
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Operation',
            'compte'       => ''
        ));
    }
    *
    /**
    ** {@inheritdoc}
    **/
    public function getBlockPrefix()
    {
        return 'appbundle_operation';
    }
}
VentilationType

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 
<?php
 
namespace AppBundle\Form;
 
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
 
class VentilationType extends AbstractType
{
    /**
    ** {@inheritdoc}
    **/
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('montantDebit', NumberType::class, array(
                'scale' => 2
            ))
            ->add('montantCredit', NumberType::class, array(
                'scale' => 2
            ))
        ;
    }
 
    public function configureOptions(OptionsResolver $resolver)
    {
      $resolver->setDefaults(array(
        'data_class' => 'AppBundle\Entity\Ventilation'
      ));
    }
 
    /**
    ** {@inheritdoc}
    **/
    public function getBlockPrefix()
    {
        return 'appbundle_ventilation';
    }
}
Tout ce passe bien, sauf qu'à l'enregistrement, l'ID Operation n'est pas enregistré en base de données comme clé étrangère dans Ventilation

Le controller :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
/**
** @param Request $request
** @param Compte $compte
** @return Response|RedirectResponse
**/
public function ajoutAction(Request $request, Compte $compte)
{
    if ($compte->getUser() != $this->getUser()) {
        throw $this->createAccessDeniedException('Accès au compte non autorisé.');
    }
 
    $o = new Operation();
    $o->setCompte($compte);
    $form = $this->createForm(OperationType::class, $o, array('compte' => $compte));
    $form->handleRequest($request);
 
    if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($o);
            $em->flush();
            return $this->redirectToRoute('compte_show', array('slug' => $compte->getSlug()));
    }
 
    return $this->render('operation/add.html.twig', array(
        'form' => $form->createView(),
        'operation' => $o,
        'type' => 'add',
    ));
}
Une idée ?

merci,

PS : La mauvaise idée serait d'ajouter une boucle pour placer "operation" dans les différentes ventilations...