Two Entities GalleryAlbum and GalleryImage have OneToMany/ManyToOne relationship:
One GalleryAlbum ==== can have ====> Many GalleryImage
Many GalleryImage === can be in ===> One GalleryAlbum
(sources below)
What is the problem?
Adding (uploading) files to GalleryAlbum
$em->persist($album)
$em->flush()
For each uploaded file GalleryAlbum class creates and adds to $images a new GalleryImage entity
My ECHO/EXIT test is not shown (GalleryImage's prePersist/preUpdate event callback function named preUpload is not triggered!)
My new images are not saved to the database? Why?
What is weird! If I do:
Adding (uploading) files
$em->persist($album)
$em->flush()
again $em->flush()
My ECHO/EXIT test is shown (GalleryImage's prePersist/preUpdate event callback function named preUpload is triggered!)
(if i delete echo/exit) My new GalleryImages are saved now!!!
Why?
Why is preUpload never triggered when I flush() once, and is triggered when I flush() twice?
# src GalleryAlbum.php
/** * @ORM\Entity * @ORM\HasLifecycleCallbacks * @ORM\Table(name="gallery_album") */ class GalleryAlbum { // some properties like id, name, description, etc /** * @ORM\OneToMany(targetEntity="GalleryImage", mappedBy="parent") */ protected $images; /* Files container. Used for upload service. Must not be persisted. */ protected $files; /* @ORM\Column(type="boolean", nullable=TRUE) * * if set to true will updateing object and calling preUpdate event callback * becouse it's always set to null in database by prePersist event callback */ protected $files_added; /** * Set container files * * @return GalleryAlbum */ public function setFiles($files) { $this->files = $files; $this->files_added = true; /* setting files_added to true forces EntityManager to update * this GalleryAlbum even if no other properties have changed */ return $this; } /** * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpload() { if(null !== $this->files) { foreach($this->files as $key => $file) { $this->addGalleryElement($file); unset($this->files[$key]); } } /* Resetting property files_added to NULL * so it always stays null in database */ $this->files_added = null; } /** * Constructing new GalleryImage and setting it's file and parent */ public function addGalleryElement($file) { $element = new GalleryImage($this, $file); $this->addGalleryImage($element); } }
# src GalleryImage.php
/** * @ORM\Entity * @ORM\HasLifecycleCallbacks * @ORM\Table(name="gallery_image") */ class GalleryImage { // some properties like id, name, description, etc /** * @ORM\ManyToOne(targetEntity="GalleryAlbum", inversedBy="images") * @ORM\JoinColumn(name="parent_id", referencedColumnName="id") */ protected $parent; /* Constructing new GalleryImage */ public function __construct($parent = null, $file = null) { if($parent) $this->setParent($parent); if($file) $this->setFile($file); } /** * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpload() { echo 'TEST: is this event callback function fired?'; exit; if(null !== $this->file) { $this->path = $this->file->guessExtension(); } $this->file_added = null; } }
The first time you call persist doctrine will only save $album and not its images. You must specify that you want doctrine to cascade the persist by specifying it in the $images declaration:
/**
* @ORM\OneToMany(targetEntity="GalleryImage", mappedBy="parent", cascade={"persist", "remove"})
*/
protected $images;
This way when you call persist($album) it will also persist your images and should trigger preUpload in your GalleryImage. There are a few different options available for cascading and they are explained well here:
Doctrine transitive persistence cascade operations
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With