Bonjour,
Le pensais avoir résolu mon problème, mais ce n'est pas le cas.
J'ai un formulaire lié à une entité annonce contenant des formulaires embarqués : un formulaire classique lié à un véhicule et un formulaire qui alimente une collection de photos. Lors de l'enregistrement d'une annonce ne contenant qu'une seule photo, tout se passe bien : l'annonce, le véhicule et la photo sont bien enregistrés dans leurs tables respectives.
Cependant, dès que j'essaie de lier plusieurs photos à l'annonce, j'obtiens l'erreur de violation de contrainte d'intégrité suivante :
Je ne parviens pas à détecter la source du problème. Pourriez-vous m'aider? Voici les sources qui pourraient aider :An exception occurred while executing 'INSERT INTO photo (name, id) VALUES (?, ?)' with params ["8435c4ae91b0277c15b669c0a50ced0b.jpeg", null]:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`roadtrip`.`photo`, CONSTRAINT `FK_14B78418BF396750` FOREIGN KEY (`id`) REFERENCES `advert` (`id`))
Dans mon entité "Advert" :
Dans mon entité "Vehicle" :
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 ... /** * @ORM\Id() * @ORM\GeneratedValue(strategy="AUTO") * @ORM\Column(type="integer") */ private $id; ... /** * @ORM\OneToOne(targetEntity="App\Entity\Vehicle", inversedBy="advert", cascade={"persist", "remove"}) * @ORM\JoinColumn(nullable=false) * * @Assert\Type(type="App\Entity\Vehicle") * @Assert\Valid() */ private $vehicle; /** * @ORM\OneToMany(targetEntity="App\Entity\Photo", mappedBy="advert", cascade={"persist"}, orphanRemoval=true) */ private $photos; public function __construct() { $this->photos = new ArrayCollection(); } ... public function getVehicle(): ?Vehicle { return $this->vehicle; } public function setVehicle(Vehicle $vehicle): self { $this->vehicle = $vehicle; $this->vehicle->setAdvert($this); return $this; } /** * @return Collection|Photo[] */ public function getPhotos(): ArrayCollection { return $this->photos; } public function setPhotos(ArrayCollection $photos) { $this->photos = $photos; } public function addPhoto(Photo $photo): self { if (!$this->photos->contains($photo)) { $this->photos[] = $photo; $photo->setAdvert($this); } return $this; } ...
Dans mon entité "Photo" :
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\Id() * @ORM\GeneratedValue() * @ORM\Column(type="integer") */ private $id; ... /** * @ORM\OneToOne(targetEntity="App\Entity\Advert", mappedBy="vehicle", cascade={"persist", "remove"}) */ private $advert; ... public function getAdvert(): ?Advert { return $this->advert; } public function setAdvert(Advert $advert): self { $this->advert = $advert; // set the owning side of the relation if necessary if ($this !== $advert->getVehicle()) { $advert->setVehicle($this); } return $this; } ...
Et enfin, dans mon 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 ... /** * @ORM\Id() * @ORM\GeneratedValue(strategy="AUTO") * @ORM\Column(type="integer") */ private $id; ... /** * @ORM\ManyToOne(targetEntity="App\Entity\Advert", inversedBy="photos") * @ORM\JoinColumn(name="id", referencedColumnName="id") */ private $advert; ... public function getAvert(): ?Advert { return $this->advert; } public function setAdvert(Advert $advert): self { $this->advert = $advert; return $this; } ...
Merci d'avance pour votre aide!
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 ... public function advertForm(Advert $advert = null, Request $request, ObjectManager $manager){ if (!$advert) { $advert = new Advert(); $vehicle = new Vehicle(); $advert->setVehicle($vehicle); /*$photo1 = new Photo(); $photo2 = new Photo(); $vehicle->setAdvert($advert); } $form = $this->createForm(AdvertType::class, $advert); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { //If it's a new advert, date assignment and expiration date assignement $now = new \DateTime('now'); $advert->setCreatedAt($now); $advert->SetExpiresAt($now->add(new DateInterval($this->getParameter('advert_active_duration')))); $photos = $advert->getPhotos(); foreach ($photos as $photo) { $advert->addPhoto($photo); // If no file is set, do nothing if (null !== $photo->getFile()) { $photo->setName(md5(uniqid()) . '.' . $photo->getFile()->guessExtension()); try { $photo->getFile()->move($this->getParameter('photos_directory'), $photo->getName()); } catch (FileException $e) { // ... handle exception if something happens during file upload } } } $manager->persist($advert); $manager->flush(); } return $this->render('road_trip/createAdvert.html.twig', ['formAdvert' => $form->createView(), 'editMode' => $advert->getId() !== null]); } ...
Edit 1 :
J'ai remarqué que la colonne "advert_id" n'était pas créée dans ma table "photo". J'ai donc modifié l'attribut "advert" comme suit dans ma classe "Photo" :
J'ai supprimé mes tables et mes fichiers de migration et j'ai refait une migration : la colonne "advert_id" est maintenant bien créée.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 /** * @ORM\ManyToOne(targetEntity="App\Entity\Advert", inversedBy="photos") * @ORM\JoinColumn(nullable=false) */ private $advert;
Lorsque je tente d'insérer une annonce, j'ai maintenant cette erreur :
Edit 2 :An exception occurred while executing 'INSERT INTO photo (name, advert_id) VALUES (?, ?)' with params ["025e2ba9ec1f70a88c18546ef202fd68.jpeg", null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'advert_id' cannot be null
En supprimant "* @ORM\JoinColumn(nullable=false)" et en permettant le null dans le champ correspondant dans ma table, ça fonctionne correctement. Cependant, je ne trouve pas ça logique ni propore, du fait qu'une photo doit impérativement être liée à une annonce. Quelqu'un a une idée?
Partager