Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Borrar imágenes en entidades borradas en cascada

10 de febrero de 2015

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

#1

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

10 febrero 2015, 13:36
#2

No me acordé de que onDelete funciona a nivel de base de datos :S.

Gracias por la respuesta.

@melencho

13 febrero 2015, 15:53