2013-09-25 91 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()); 
     } 
    } 
} 

這個解決方案能正常工作在我的網站。