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!