Erreur de violation de contrainte

Par dubitoph, il y a 7 ans


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 :

"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))"

Je ne parviens pas à détecter la source du problème. Pourriez-vous m'aider? Voici les sources qui pourraient aider :

Dans mon entité "Advert" :

... /** * @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é "Vehicle" :

... /** * @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; } ...

Dans mon entité "Photo" :

... /** * @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; } ...

Et enfin, dans mon controller :

... public function advertForm(Advert $advert = null, Request $request, ObjectManager $manager){ if (!$advert) { $advert = new Advert(); $vehicle = new Vehicle(); $advert->setVehicle($vehicle); $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" :

"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"

Edit 2 :

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?

Merci d'avance pour votre aide!

1 réponse

dubitoph, il y a 7 ans

Problème résolu