Bonjour !
Alors voilà j'ai un problème depuis hier concernant les formulaires et les entités. Je vous explique :
J'ai 2 entités :
- L'entité Test contient 3 attributs : date, experimentateur et typeTest (qui est en fait une relation ManyToOne vers l'entité TypeTest)
- L'entité ResultatTestSimple qui hérite de ResultatTest qui contient, entre autres, les attributs suivants : mesure, description et test (qui est là aussi une relation ManyToOne vers Test).
Voici le code de ces deux entités :
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 /** * Test * * @ORM\Table(name="test") * @ORM\Entity(repositoryClass="MMDN\Microcebes\MicrocebesBundle\Entity\TestRepository") */ class Test { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\ManyToOne(targetEntity="TypeTest") * @ORM\JoinColumn(name="type_test_id", referencedColumnName="id") **/ private $typeTest; /** * @ORM\OneToMany(targetEntity="ResultatTest", mappedBy="test") **/ private $resultatsTests; /** * @var \DateTime * * @ORM\Column(name="date", type="date", nullable=false) */ private $date; /** * @var string * * @ORM\Column(name="experimentateur", type="string", length=50, nullable=false) */ private $experimentateur; // getters et setters. }Dans l'entité Test, le triplet (date, experimentateur, typeTest) est unique.
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 /** * ResultatTest * * @ORM\Table(name="resultat_test") * @ORM\Entity(repositoryClass="MMDN\Microcebes\MicrocebesBundle\Entity\ResultatTestRepository") * @ORM\InheritanceType("JOINED") * @ORM\DiscriminatorColumn(name="discr", type="string") * @ORM\DiscriminatorMap({ * "simple" = "ResultatTestSimple", * "geno" = "TestGenotypage", * "immuno" = "TestImmunologique", * "induc" = "TestInduction", * "irm" = "Irm", * "sequence" = "SequencageAdn"}) */ class ResultatTest { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\ManyToOne(targetEntity="Animal", inversedBy="resultatsTests") * @ORM\JoinColumn(name="animal_id", referencedColumnName="id", nullable=false) **/ private $animal; /** * @ORM\ManyToOne(targetEntity="Test", inversedBy="resultatsTests", cascade={"persist"}) * @ORM\JoinColumn(name="test_id", referencedColumnName="id", nullable=false) **/ private $test; // getters et setters...
Je souhaite avoir un formulaire qui représente un Test. Ce formulaire s'appelle TestSelectorType et est déclaré comme service puisqu'il a pour but d'être inclu dans d'autres formulaires, notamment ResultatTestSimpleType.
Voici le code de TestSelectorType
Ainsi, sur la page de création ou d'édition d'un RésultatTestSimple, nous aurons les champs suivants :
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 class TestSelectorType extends AbstractType { /** * @var ObjectManager */ private $om; /** * @param ObjectManager $om */ public function __construct(ObjectManager $om) { $this->om = $om; } /** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('date', 'date', [ 'label' => 'Date du test', 'required' => true, 'widget' => 'single_text' ]) ->add('experimentateur', null, [ 'label' => 'Expérimentateur', 'required' => true, ]) ->add('typeTest', 'entity', [ 'class' => 'MMDNMicrocebesMicrocebesBundle:TypeTest', 'empty_value' => 'Sélectionnez le type de test.', 'required' => true, 'multiple' => false, 'property' => 'label' ]); } /** * @param OptionsResolverInterface $resolver */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'MMDN\Microcebes\MicrocebesBundle\Entity\Test' )); } /** * @return string */ public function getName() { return 'test_selector'; } }
mesure, description, date du test, experimentateur du test, type du test. Les trois derniers étant en fait issus de TestSelectorType.
Lorsque l'utilisateur soumet le formulaire, le système est censé regarder les attributs liés au test (les 3 derniers), récupérer ce test s'il existe ou créer ce test s'il n'existe pas et il est censé faire $resultatTestSimple->setTest($monNouveauTest). Ceci a pour but de réutiliser les tests existants au lieu de créer un Test par ResultatTestSimple.
Pour ce faire, j'ai essayé de mettre un DataTransformer pour TestSelectorType qui, en faisant reverseTransform(), récupère un test existant ou le crée. Mais ça ne fonctionne que quand je crée un nouveau ResultatTestSimple. A l'édition d'un ResultatTestSimple, un phénomène un peu spécial se produit : Au lieu de faire simplement $resultatTestSimple->setTest($testExistantRécupéré), le système me fait $resultatTestSimple->setTest($testExistantRécupéré) mais il me met aussi à jour l'ancien test ! Ce qui fait que je me retrouve avec deux tests identiques : Celui qui a été récupéré ET celui qui était déjà lié avec le $resultatTestSimple.
Voici le code du DataTransformer. Ce Transformer est ajouté à TestSelectorType à l'aide de $builder->addModelTransformer($transformer);
J'ai donc essayé de passer par un Event de type SUBMIT et POST_SUBMIT sur TestSelectorType mais il me met simplement à jour l'ancien test.
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 class TestDataTransformer implements DataTransformerInterface { /** * @var ObjectManager */ private $om; /** * @param ObjectManager $om */ public function __construct(ObjectManager $om) { $this->om = $om; } public function transform($test) { if(null === $test) return null; if(!$test instanceof Test) { throw new UnexpectedTypeException($test,'MMDN\Microcebes\MicrocebesBundle\Entity\Test'); } return $test; } public function reverseTransform($test) { // Ici, $test est déjà créé if (! $test instanceof Test) { throw new TransformationFailedException("The test couldn't be guessed"); } /** @var TestRepository $testRepo */ $testRepo = $this->om->getRepository('MMDNMicrocebesMicrocebesBundle:Test'); $findTest = $testRepo->findOneByDateAndExpAndType( $test->getDate(), $test->getExperimentateur(), $test->getTypeTest() ); // $findTest est le test que nous avons recherché. S'il vaut null, aucun test avec le même triplet n'a été trouvé. S'il vaut ! null, c'est qu'un test existant a été trouvé. Dans ce cas, on retourne le test existant. if($findTest) { return $findTest; } $newTest = new Test(); $newTest->setDate($test->getDate()); $newTest->setExperimentateur($test->getExperimentateur()); $newTest->setTypeTest($test->getTypeTest()); return $test; } }
Voici le TestSelectorType quand j'utilise un Event :
Du coup j'ai essayé de mettre le même Event mais sur le formulaire qui utilise TestSelectorType (donc sur ResultatTestSimpleType), mais j'ai exactement le même résultat qu'avec le DataTransformer !
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 class TestSelectorType extends AbstractType { /** * @var ObjectManager */ private $om; /** * @param ObjectManager $om */ public function __construct(ObjectManager $om) { $this->om = $om; } /** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('date', 'date', [ 'label' => 'Date du test', 'required' => true, 'widget' => 'single_text' ]) ->add('experimentateur', null, [ 'label' => 'Expérimentateur', 'required' => true, ]) ->add('typeTest', 'entity', [ 'class' => 'MMDNMicrocebesMicrocebesBundle:TypeTest', 'empty_value' => 'Sélectionnez le type de test.', 'required' => true, 'multiple' => false, 'property' => 'label' ]) ->addEventListener( FormEvents::SUBMIT, function(FormEvent $event) { $test = $event->getData(); // On cherche si un test existe déjà avec les mêmes données /** @var TestRepository $testRepository */ $testRepository = $this->om ->getRepository('MMDNMicrocebesMicrocebesBundle:Test'); $findTest = $testRepository ->findOneByDateAndExpAndType( $test->getDate(), $test->getExperimentateur(), $test->getTypeTest() ); if($findTest) { $event->setData($findTest); } } ); } /** * @param OptionsResolverInterface $resolver */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'MMDN\Microcebes\MicrocebesBundle\Entity\Test' )); } /** * @return string */ public function getName() { return 'test_selector'; } }
Je suis donc bloqué depuis hier... Je n'arrive pas à avancer, et j'ai besoin de votre aide !
Merci d'avance ! =)
Partager