I have two entities in my code: Session and SessionPicture.
There is a OneToOne relationship between Session and SessionPicture. SessionPicture is the mapping entity and Session is the inverse one.
Session has an attribute called "Slug", which is generated thanks to the StofDoctrineExtensionsBundle https://github.com/stof/StofDoctrineExtensionsBundle, and using the Gedmo\Sluggable annotation.
I have a form to create a Session (so a SessionType), and this SessionType embeds a SessionPictureType. The SessionPicture class contains a file attribute (UploadedFile class) and I have used LifecycleEvents (PostPersist/PostUpdate) to upload the file of the SessionPicture, and give it the "slug" property of the related Session when I save it.
My issue is that when I try to change another property of my SessionPicture (let's say "alt") and give it the value of the "slug" of the session , I cannot do it in the PostPersist Lifecycle and then save it to my database, because this event takes place after the onFlush, which is too late. I have to do it in the PrePersist Lifecyle. But then the "slug" of my session is not available yet, because it is generated during the onFlush by the extension.
So how can I get the slug of the related session in the prePersist lifecyle?
(PS: I have a found a solution, which is to persist the session in my controller, flush with the Manager, and then to persist again and redo a flush() but it is not very elegant).
Please find my code below:
/** * Session * * @ORM\Table() * @ORM\Entity(repositoryClass="MyBundle\Entity\SessionRepository") * @ORM\HasLifecycleCallbacks() */
class Session
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* @ORM\OneToOne(targetEntity="MyBundle\Entity\SessionPicture", cascade={"persist", "remove"}, mappedBy="session")
* @ORM\JoinColumn(name="session_picture_id", referencedColumnName="id", nullable=true)
*/
private $sessionPicture;
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set sessionPicture
*
* @param \MyBundle\Entity\SessionPicture $sessionPicture
*
* @return Session
*/
public function setSessionPicture(MyBundle\Entity\SessionPicture $sessionPicture = null)
{
$this->sessionPicture = $sessionPicture;
return $this;
}
/**
* Get sessionPicture
*
* @return \MyBundle\Session\SessionPicture
*/
public function getSessionPicture()
{
return $this->sessionPicture;
}
And my SessionPicture code:
/**
* @var string
*
* @ORM\Column(name="alt", type="string", length=255, nullable=true)
*/
private $alt;
/**
* @var string
*
* @ORM\Column(name="path", type="string", length=255, nullable=true)
*/
private $path;
/**
* @ORM\OneToOne(targetEntity="MyBundle\Entity\Session", inversedBy="sessionPicture")
*/
private $session;
public $file;
private $fileNameForRemove;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set extension
*
* @param string $extension
*
* @return SessionPicture
*/
public function setExtension($extension)
{
$this->extension = $extension;
return $this;
}
/**
* Get extension
*
* @return string
*/
public function getExtension()
{
return $this->extension;
}
/**
* Set alt
*
* @param string $alt
*
* @return SessionPicture
*/
public function setAlt($alt)
{
$this->alt = $alt;
return $this;
}
/**
* Get alt
*
* @return string
*/
public function getAlt()
{
return $this->alt;
}
/**
* Set path
*
* @param string $path
*
* @return SessionPicture
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Get path
*
* @return string
*/
public function getPath()
{
return $this->path;
}
/**
* Set session
*
* @param \MyBundle\Entity\Session $session
*
* @return SessionPicture
*/
public function setSession(\NyBundle\Entity\Session $session = null)
{
$this->session = $session;
return $this;
}
/**
* Get session
*
* @return \MyBundle\Entity\Session
*/
public function getSession()
{
return $this->session;
}
/**
* @ORM\PrePersist()
* @ORM\PreUpdate()
*/
public function preUpload()
{
if($this->file === null)
return ;
$extension = $this->file->guessExtension();
$this->extension = (string)$extension;
My issue is below, I cannot get the slug before the flush of the session
$this->alt = $this->getSession()->getSlug();
}
/**
* @ORM\PostPersist()
* @ORM\PostUpdate()
*/
public function upload()
{
But here, I can get the slug because my session has already been flushed and the slug generated
$this->alt = $this->getSession()->getSlug();
$this->path = $this->alt.'.'.$this->extension;
if ($this->file === null)
return ;
$this->file->move($this->getUploadRootDir(), $this->path);
unset($this->file);
}
Finally, here is an extract my controller code:
$form->handlerequest($request);
$validator = $this->get('validator');
$errorList = $validator->validate($session);
if (count($errorList) == 0)
{
$em = $this->getDoctrine()->getManager();
$em->persist($session);
$em->flush();
$em->persist($session);
$em->flush();
As you can see, I had to persist the $session and to flush it once, so that the slug is generated at the flush. Then persist again so that the slug is now available for the "alt" property of the SessionPicture at the prePersist n2, and flush again to save the alt property. But it is not very clean.
Thanks for any hel or advice. Thanks.