2013-09-25 88 views
7

我是symfony2的新手。 我正在使用liipImagineBundle管理图像缩略图。 我有一个产品实体类,它使用生命周期回调来管理产品图像。使用liipImagineBundle删除/更新缓存图像更新/删除记录

Product.php

<?php 

namespace Svipl\AdminBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Gedmo\Mapping\Annotation as GEDMO; 
use Symfony\Component\HttpFoundation\File\UploadedFile; 

/** 
* Svipl\AdminBundle\Entity\Product 
* @ORM\Entity 
* @ORM\Table(name="product") 
* @ORM\Entity(repositoryClass="Svipl\AdminBundle\Entity\ProductRepository") 
* @ORM\HasLifecycleCallbacks 
*/ 
class Product{ 
    /** 
    * @ORM\Column(type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @ORM\Column(type="string", length=25, unique=true) 
    */ 
    private $name; 

    /** 
    * @ORM\Column(type="text") 
    */ 
    private $description; 

    /** 
    * @ORM\Column(type="float", length=8) 
    * @var unknown 
    */ 
    private $price; 

    /** 
    * @GEDMO\Timestampable(on="update") 
    * @ORM\Column(name="updated_at", type="datetime") 
    */ 
    private $updated_at; 

    /** 
    * @GEDMO\Timestampable(on="create") 
    * @ORM\Column(name="created_at", type="datetime") 
    */ 
    private $created_at; 

    /** 
    * @ORM\ManyToOne(targetEntity="Category", inversedBy="products") 
    * @ORM\JoinColumn(name="category_id", referencedColumnName="id") 
    */ 
    protected $category; 

    /** 
    * @ORM\Column(name="image", type="string", length=50) 
    */ 
    private $image; 

    public function getAbsolutePath() 
    { 
     return null === $this->image 
     ? null 
     : $this->getUploadRootDir().'/'.$this->image; 
    } 

    public function getWebPath() 
    { 
     return null === $this->image 
     ? null 
     : $this->getUploadDir().'/'.$this->image; 
    } 

    protected function getUploadRootDir() 
    { 
     // the absolute directory path where uploaded 
     // documents should be saved 
     return __DIR__.'/../../../../web/'.$this->getUploadDir(); 
    } 

    protected function getUploadDir() 
    { 
     // get rid of the __DIR__ so it doesn't screw up 
     // when displaying uploaded doc/image in the view. 
     return 'uploads/product'; 
    } 

    private $file; 

    /** 
    * Get file. 
    * 
    * @return UploadedFile 
    */ 
    public function getFile() 
    { 
     return $this->file; 
    } 

    /** 
    * Get id 
    * 
    * @return integer 
    */ 
    public function getId() 
    { 
     return $this->id; 
    } 

    /** 
    * Set name 
    * 
    * @param string $name 
    * @return Product 
    */ 
    public function setName($name) 
    { 
     $this->name = $name; 

     return $this; 
    } 

    /** 
    * Get name 
    * 
    * @return string 
    */ 
    public function getName() 
    { 
     return $this->name; 
    } 

    /** 
    * Set description 
    * 
    * @param string $description 
    * @return Product 
    */ 
    public function setDescription($description) 
    { 
     $this->description = $description; 

     return $this; 
    } 

    /** 
    * Get description 
    * 
    * @return string 
    */ 
    public function getDescription() 
    { 
     return $this->description; 
    } 

    /** 
    * Set price 
    * 
    * @param float $price 
    * @return Product 
    */ 
    public function setPrice($price) 
    { 
     $this->price = $price; 

     return $this; 
    } 

    /** 
    * Get price 
    * 
    * @return float 
    */ 
    public function getPrice() 
    { 
     return $this->price; 
    } 

    /** 
    * Set updated_at 
    * 
    * @param \DateTime $updatedAt 
    * @return Product 
    */ 
    public function setUpdatedAt($updatedAt) 
    { 
     $this->updated_at = $updatedAt; 

     return $this; 
    } 

    /** 
    * Get updated_at 
    * 
    * @return \DateTime 
    */ 
    public function getUpdatedAt() 
    { 
     return $this->updated_at; 
    } 

    /** 
    * Set created_at 
    * 
    * @param \DateTime $createdAt 
    * @return Product 
    */ 
    public function setCreatedAt($createdAt) 
    { 
     $this->created_at = $createdAt; 

     return $this; 
    } 

    /** 
    * Get created_at 
    * 
    * @return \DateTime 
    */ 
    public function getCreatedAt() 
    { 
     return $this->created_at; 
    } 

    /** 
    * Set category 
    * 
    * @param \Svipl\AdminBundle\Entity\Category $category 
    * @return Product 
    */ 
    public function setCategory(\Svipl\AdminBundle\Entity\Category $category = null) 
    { 
     $this->category = $category; 

     return $this; 
    } 

    /** 
    * Get category 
    * 
    * @return \Svipl\AdminBundle\Entity\Category 
    */ 
    public function getCategory() 
    { 
     return $this->category; 
    } 

    /** 
    * Set image 
    * 
    * @param string $image 
    * @return Product 
    */ 
    public function setImage($image) 
    { 
     $this->image = $image; 

     return $this; 
    } 

    /** 
    * Get image 
    * 
    * @return string 
    */ 
    public function getImage() 
    { 
     return $this->image; 
    } 

    private $temp; 

    /** 
    * Sets file. 
    * 
    * @param UploadedFile $file 
    */ 
    public function setFile(UploadedFile $file = null) 
    { 
     $this->file = $file; 
     // check if we have an old image path 
     if (isset($this->image)) { 
      // store the old name to delete after the update 
      $this->temp = $this->image; 
      $this->image = null; 
     } else { 
      $this->image = 'initial'; 
     } 
    } 

    /** 
    * @ORM\PrePersist() 
    * @ORM\PreUpdate() 
    */ 
    public function preUpload() 
    { 
     if (null !== $this->getFile()) { 
      // do whatever you want to generate a unique name 
      $filename = sha1(uniqid(mt_rand(), true)); 
      $this->image = $filename.'.'.$this->getFile()->guessExtension(); 
     } 
    } 

    /** 
    * @ORM\PostPersist() 
    * @ORM\PostUpdate() 
    */ 
    public function upload() 
    { 
     if (null === $this->getFile()) { 
      return; 
     } 

     // if there is an error when moving the file, an exception will 
     // be automatically thrown by move(). This will properly prevent 
     // the entity from being persisted to the database on error 
     $this->getFile()->move($this->getUploadRootDir(), $this->image); 

     // check if we have an old image 
     if (isset($this->temp)) { 
      // delete the old image 
      unlink($this->getUploadRootDir().'/'.$this->temp); 
      // clear the temp image path 
      $this->temp = null; 
     } 
     $this->file = null; 
    } 

    /** 
    * @ORM\PostRemove() 
    */ 
    public function removeUpload() 
    { 
     if ($file = $this->getAbsolutePath()) { 
      unlink($file); 
     } 
    } 
} 

config.yml

... 
liip_imagine: 
    filter_sets: 
     my_thumb: 
      quality: 75 
      filters: 
       thumbnail: { size: [120, 90], mode: outbound } 

缩略图生成代码

... 

<img src="{{ asset('uploads/product/' ~ form_object.vars.value.image) | imagine_filter('my_thumb', true) }}" /> 

... 

缩图正确地产生。

但我无法找到更新/删除缓存的图像,而原始图像更改或删除与表单的方式。

+0

当有人通过表单改变图像时,不能再次启动代码?他们如何通过上传新图片或其他内容来改变它? –

+0

我有两个要求 1)当用户删除产品时,原始图像将被删除,我也想删除它的缩略图(如果存在) 2)当用户更新产品图像时,应删除旧图像以及其缓存缩略图如果存在 –

回答

9

你应该注册一个preUpdate和preRemove event listener/subscriber,注入所需的服务并删除那里的图像。

由于您无权访问服务容器(并且不应将服务注入到实体中),因此无法查询LiipImagineBundle的服务以使用生命周期事件从实体内部获取缓存文件。

您可以注入服务liip_imagine.cache.manager并使用它的remove()方法从缓存中删除图像。

2

不要忘记调用liip_imagine.cache.manager的resolve()方法。否则,它不会删除您的缓存图像。

如下所述:https://github.com/liip/LiipImagineBundle/issues/132

$cacheManager = $this->get('liip_imagine.cache.manager'); 
$cacheManager->resolve($this->getRequest(), $pngPath, $filter); 
$cacheManager->remove($pngPath, $filter); 
2

我知道这个问题是有点老了,但万一有人找一些代码(我使用SF 2.3)。我有这个文件删除的要求。在我的项目中,我使用VichUploaderBundle来处理文件上传,并使用LiipImagineBundle来处理这些图像的缩略图生成。当实体被删除时,应该删除上传的文件以及缩略图(如果有的话)。我已经实现了一个学说侦听器,则删除前方法如下:

public function preRemove(LifecycleEventArgs $args) 
{ 
    $filter = 'thumbnail'; //the filter that imagine bundle uses 
    $fileEntity = $args->getEntity(); 
    if($fileEntity instanceof FileEntity) 
    { 
     //get the path to the uploaded file, relative to the web url 
     $sourcePath = $this->uploaderStorage->resolveUri($fileEntity, "file");  

     $this->liipCacheManager->remove($sourcePath, $filter); 
    } 
} 
3

你必须创建一个监听实体和创建服务。 该服务将调用此实体每个你想要的事件:这里的PostUpdate和你的产品的preRemove。

在实体监听器中,您为每个事件设置了一个方法,并且您只需清除每个方法上的缓存或执行其他任何您想要的操作。

下面的例子来源于此post

服务

services: 
    project.cacheimage_listener: 
     class: Acme\Listener\CacheImageListener 
     arguments: ["@liip_imagine.cache.manager"] 
     tags: 
      - { name: doctrine.event_listener, event: postUpdate } 
      - { name: doctrine.event_listener, event: preRemove } 

实体监听

<?php 
namespace Acme\Listener; 

use Doctrine\ORM\Event\LifecycleEventArgs; 
use Acme\Entity\Image; 

class CacheImageListener 
{ 
    protected $cacheManager; 

    public function __construct($cacheManager) 
    { 
     $this->cacheManager = $cacheManager; 
    } 

    public function postUpdate(LifecycleEventArgs $args) 
    { 
     $entity = $args->getEntity(); 

     if ($entity instanceof Image) { 
// clear cache of thumbnail 
      $this->cacheManager->remove($entity->getUploadDir()); 
     } 
    } 

// when delete entity so remove all thumbnails related 
    public function preRemove(LifecycleEventArgs $args) 
    { 
     $entity = $args->getEntity(); 

     if ($entity instanceof Image) { 

      $this->cacheManager->remove($entity->getWebPath()); 
     } 
    } 
} 

这个解决方案能正常工作在我的网站。