Muy buenas,
Tengo un problema al respecto de estas dos entidades: Producto
y Archivo
. Producto
tiene una foto principal y cuando quiero guardar más de una foto, uso la entidad Archivo
para guardar las fotos adicionales relacionadas con un producto. He usado la configuración de este artículo del cookbook de Symfony
Al borrar un producto se elimina el registro de dicho producto y en cascada los registros relacionados en Archivo
. La imagen de producto se elimina del servidor pero las imágenes referenciadas en Archivo
no se eliminan y se mantienen en el servidor a pesar de tener indicado el unlink
en el PostRemove
.
No sé si estoy haciendo algo mal. ¿Hay alguna manera de conseguir eliminarlas directamente o la eliminación de esas imágenes hay que hacerla a manubrio?
Gracias por la atención
/** * Producto * @ORM\Table() * @ORM\Entity() * @ORM\HasLifecycleCallbacks */ class Producto { // ... /** * @Assert\Image(maxSize="4096k", mimeTypes={"image/png", "image/jpeg", "image/gif"}, minWidth=100, minHeight=100) */ protected $file; protected $temp; // ... } /** * Archivo * @ORM\Table() * @ORM\Entity() * @ORM\HasLifecycleCallbacks */ class Archivo { // ... /** * @ORM\ManyToOne(targetEntity="Proyecto\ProductoBundle\Entity\Producto") * @ORM\JoinColumn(name="producto_id", referencedColumnName="id", onDelete="CASCADE") */ protected $producto; // ... /** * @Assert\Image(maxSize="3072k", mimeTypes={"image/png", "image/jpeg", "image/gif"}, minWidth=100, minHeight=100) */ protected $file; protected $temp; public function setFile(UploadedFile $file = null) { $this->file = $file; if(isset($this->ruta)) { $this->temp = $this->ruta; $this->ruta = null; } else { $this->ruta = 'initial'; } return $this; } public function getFile(){ return $this->file; } /** * Set ruta * @param string $ruta * @return Archivo */ public function setRuta($ruta){ $this->ruta = $ruta; return $this; } /** * Get ruta * @return string */ public function getRuta(){ return $this->ruta; } public function getAbsolutePath(){ return null === $this->ruta ? null : $this->getUploadRootDir().'/'.$this->ruta; } public function getWebPath(){ return null === $this->ruta ? null : $this->getUploadDir().'/'.$this->ruta; } public function getUploadRootDir(){ return __DIR__.'/../../../../web/'.$this->getUploadDir(); } protected function getUploadDir(){ return 'uploads/gallery'; } /** * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpload(){ if(null !== $this->getFile()) { $filename = sha1(uniqid(mt_rand(), true)); $this->ruta = $filename . '.' . $this->getFile()->guessExtension(); } } /** * @ORM\PostPersist() * @ORM\PostUpdate() */ public function upload(){ if( null === $this->getFile()) { return; } $this->getFile()->move($this->getUploadRootDir(), $this->ruta); if (isset($this->temp)) { unlink($this->getUploadRootDir().'/'.$this->temp); $this->temp = null; } $this->file = null; } /** * @ORM\PostRemove() */ public function removeUpload(){ if ($file = $this->getAbsolutePath()) { unlink($file); } } }
Respuestas
Buenas,
Pensaría que el problema es el onDelete="CASCADE"
definido en la asociación Producto -> Archivo
, ya que es la base de datos la que está eliminando los registros en archivos, sin que doctrine (ni php) se entere, debes usar cascade={"remove"}
(En la asociación del lado de la Entidad Producto) para que la eliminación sea Lógica y la haga Doctrine, llamando así a los respectivos Callback.
Mas info acá:
Saludos!
@manuel_j555
No me acordé de que onDelete funciona a nivel de base de datos :S.
Gracias por la respuesta.
@melencho