Bonjour,

J'ai un problème étrange que je n'arrive décidément pas à comprendre :

- lorsque je crée un nouvel enregistrement d'une entité et que je laisse un champ vide qui est obligatoire, le formulaire ne passe pas la validation,
- lorsque je modifie un enregistrement existant en laissant vide un champ qui était déjà vide, le formulaire ne passe pas non plus la validation.

Jusque là tout va bien, c'est le comportement attendu.

Par contre, lorsque je modifie un enregistrement en vidant un champ qui était renseigné, le formulaire passe la validation et évidemment une exception est levée :

Catchable Fatal Error: Argument 1 passed to MyBundle\Entity\Offre::setContact() must be an instance of MyBundle\Entity\Contact, null given,
Voici les parties de mon code qui peuvent être intéressante pour essayer de comprendre cette exception :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
class Offre {
    /**
     *
     * @var MyBundle\Entity\Contact contact
     * @ORM\ManyToOne(targetEntity="Contact", inversedBy="offresAdm")
     * @ORM\JoinColumn(name="contact_id", referencedColumnName="id")
     * @Assert\NotBlank(message="Veuillez indiquer un contact administratif")
     */
    protected $contact;
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
class OffreType extends AbstractType
{
    protected $offre;
 
    public function buildForm( FormBuilderInterface $builder, array $options )
    {        
        $this->offre = $builder->getData();
    	$builder->add('contact', 'entity', array(
    			'label'         =>  'Contact administratif',
    			'required'		=>	true,
    			'empty_value'	=>	'--- Choisir un contact ---',
    			'class'         =>  'MyBundle:Contact',
    			'query_builder' =>  function(EntityRepository $er) {
    				return $er->createQueryBuilder('q')
    				->where('q.type=?1')
    				->orderBy('q.nom','asc')
    				->setParameter(1,1);
    			}
    	));
    	$builder->add('cfc', 'entity', array(
    			'label'         =>  'Responsable pédagogique (CFC)',
    			'class'         =>  'MyBundle:Contact',
    			'empty_value'	=>	'--- Choisir un cfc ---',
    			'required'		=>	true,
    			'query_builder' =>  function(EntityRepository $er) {
    				return $er->createQueryBuilder('q')
    				->where('q.type=?1')
    				->orderBy('q.nom','asc')
    				->setParameter(1,2);
    			}
    	));
 
    	$builder->add('formacodes', null, array('label'=>"Formacodes"));
 
    	$builder->add('codesRome', 'entity', array(
	            'label'         =>  "Codes ROME",
	            'required'      =>  false,
	            'multiple'      =>  true,
	            'class'         =>  'MyBundle:CodeRome',
	            'query_builder' =>  function(EntityRepository $er) {
	                return $er->createQueryBuilder('q')
	                          ->groupBy('q.nomV3')
	                          ->orderBy('q.codeV3');
	            }
	        ));        
        $builder->add('codesNsf', null, array(
            'label'     =>  "Codes NSF",
            'required'  =>  false
        ));
 
    	if ( ! $this->offre->getConventionnement() )
    	{
	        $builder->add('nom', null, array(
	            'label'=>   'Intitulé de la formation'
	        ));
	        $builder->add('organisme', null, array(
	            'property'      =>  'nom',
	         	'empty_value'	=>	'--- Choisir un organisme ---'
	        ));
	        $builder->add('modaliteEnseignement', null, array(
	            'label'         =>  "Modalité d'enseignement",
	            'property'      =>  'nom',
	        	'empty_value'	=>	"--- Choisir une modalité ---"
	        ));
	        $builder->add('objectifGeneral', null, array(
	            'label'         =>  'Objectif général',
	            'property'      =>  'nom',
	         	'empty_value'	=>	'--- Choisir un objectif général ---'
	        ));
	        $builder->add('objectifDetaille',   'textarea', array(
	            'label'=>"Objectif détaillé"
	        ));
	        $builder->add('nombreHeuresTotal', 'integer', array(
	            'label'         => "Nombre total d'heures",
	            'attr'          => array('maxlength'=>4) 
	        ));
	        $builder->add('niveauEntree', null, array(
	            'label'         =>  "Niveau d'entrée",
	            'property'      =>  'nom',
	        	'empty_value'	=>	'--- Choisir un niveau d\'entree ---'
	        ));
	        $builder->add('priseEnChargeFrais', null, array('label'=>"Prise en charge des frais"));
	        $builder->add('conditionsPriseEnCharge',   'textarea', array(
	            'label'         =>  "Conditions de prise en charge des frais",
	            'required'      =>  false
	        ));
	        $builder->add('certifiante', null, array('label'=>'Diplomant/certifiant'));
 
	        $builder->add('diplomes', null, array(
	            'label'         =>  'Diplômes',
	            'property'      =>  'nom'
	        ));
 
	        $builder->add('infoDerniereMinute',  'textarea', array(
	            'label'=>'Informations de dernière minute',
	            'required'=>false
	        ));
	        $builder->add('contenu',   'textarea');
	        $builder->add('resultatsAttendus',   'textarea', array(
	            'label'=>"Résultat(s) attendu(s)",
	            'required'=>false
	        ));
	        $builder->add('rythmeFormation', null, array(
	            'label'         =>  'Rythme de formation',
	            'property'      =>  'nom',
	        	'empty_value'	=>	"--- Choisir un rythme de formation ---"
	        ));
	        $builder->add('modaliteAlternance', null, array(
	            'label'         =>  "Modalité d'alternance",
	            'property'      =>  'nom',
	        	'empty_value'	=>	"--- Choisir une modalité ---"
	        ));
	        $builder->add('modaliteEntreesSorties', null, array(
	            'label'         =>  "Modalité d'entrées-sorties",
	            'property'      =>  'nom',
	        	'empty_value'	=>	"--- Choisir une modalité ---"
	        ));
	        $builder->add('modalitePedagogique', null, array(
	            'label'         =>  "Modalité pédagogique",
	            'property'      =>  'nom',
	        	'empty_value'	=>	"--- Choisir une modalité ---"
	        ));
	        $builder->add('publicsVises', null, array(
	            'label'         =>  "Publics visés",
	            'property'      =>  'nom'
	        ));
    	}
    }
 
    public function getName()
    {
        return 'offre';
    }
 
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
    	$resolver->setDefaults(array(
            'data_class'    =>  'MyBundle\Entity\Offre'
        ));
    }
}
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
/**
     * @Route("/offre/new", name="_offre_new")
     * @Secure(roles="ROLE_ADMIN")
     * @Template
     */
    public function newAction() 
    {
        $request = $this->get('request');
        $offre = new Offre();
        $form = $this->createForm( new OffreType(), $offre );
 
        $process = $this->processForm($request, $form, $offre);
        if ( $process === true )
        {
            $this->get('session')->getFlashBag()->add('success', 'Offre "'.$offre->getNom().'"  créée');
            return $this->redirect( $this->generateUrl('_offre_index'));
        }
        else if ( $process == "errors" )
        {
            return array('form'=>$form->createView(), 'offre'=>$offre, 'errors'=>true);
        }
 
        return array('form'=>$form->createView(), 'offre'=>$offre,);
    }
 
    /**
     * @Route("/offre/{slug}/edit", name="_offre_edit")
     * @Secure(roles="ROLE_ADMIN")
     * @Template
     */
    public function editAction($slug) 
    {
        $request = $this->get('request');
        $offre = $this->findOffre($slug);
        $form = $this->createForm( new OffreType(), $offre );
 
        $process = $this->processForm($request, $form, $offre);
        if ( $process === true )
        {
            $this->get('session')->getFlashBag()->add('success','Offre "'.$offre->getNom().'" modifiée');
            return $this->redirect( $this->generateUrl('_offre_index'));
        }
        else if ( $process === "errors" )
        {
            return array('form'=>$form->createView(), 'offre'=>$offre, 'errors'=>true);
        }
        return array('form'=>$form->createView(), 'offre'=>$offre);
    }   
 
    protected function processForm($request, $form, $offre)
    {        
        if ( $request->getMethod() == 'POST' )
        {
            $form->bindRequest($request);
 
            if ($form->isValid())
            {                
                $em = $this->getEntityManager();
                $em->getFilters()->disable('soft-deleteable');
                $em->persist($offre);
                $em->flush();
                $em->getFilters()->enable('soft-deleteable');
                return true;
            }
            return "errors";
        }
        return false;
    }
Là j'ai pris le champ 'contact' en exemple, mais le problème se reproduit avec les champs 'organisme' ou 'cfc' et sans doute avec d'autres.
Le formulaire pourrait-il être validé parce que la validation prend en compte l'ancienne valeur du champ (un résidu ?). J'avoue que je suis un peu perturbé par ce problème...

Merci d'avance pour votre aide !