2013-09-25 68 views
7

Tôi mới dùng symfony2. Tôi đang sử dụng liipImagineBundle để quản lý hình thu nhỏ của hình ảnh. Tôi có một lớp thực thể sản phẩm sử dụng Cuộc gọi lại vòng đời để quản lý hình ảnh sản phẩm.Xóa/cập nhật hình ảnh được lưu trong bộ nhớ cache trong khi cập nhật/xóa bản ghi với 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 } 

hệ Thumbnail đang

... 

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

... 

Thumbnail tạo một cách chính xác.

Nhưng tôi không thể tìm cách cập nhật/xóa hình ảnh được lưu trong bộ nhớ cache trong khi thay đổi hình ảnh gốc hoặc xóa bằng biểu mẫu.

+0

Không thể khởi chạy lại mã thế hệ khi ai đó thay đổi hình ảnh máng một biểu mẫu? Làm thế nào để họ thay đổi nó, bằng cách tải lên một hình ảnh mới hoặc một cái gì đó? –

+0

Tôi có hai yêu cầu 1) khi người dùng xóa sản phẩm tại thời điểm hình ảnh ban đầu sẽ bị xóa và tôi cũng muốn xóa hình thu nhỏ nếu tồn tại 2) khi người dùng cập nhật hình ảnh sản phẩm sau đó xóa hình ảnh cũ hình thu nhỏ nếu tồn tại –

Trả lời

9

Bạn nên đăng ký preUpdate và preRemove event listener/subscriber, tiêm dịch vụ cần thiết và xóa hình ảnh trong đó.

Vì bạn không có quyền truy cập vào vùng chứa dịch vụ (và bạn không nên tiêm dịch vụ vào thực thể của mình), bạn không thể truy vấn dịch vụ của LiipImagineBundle để lấy tệp được lưu trong bộ nhớ cache từ bên trong thực thể của bạn bằng các sự kiện Vòng đời.

Bạn có thể tiêm dịch vụ liip_imagine.cache.manager và sử dụng phương thức remove() để xóa hình ảnh khỏi bộ nhớ cache.

2

Đừng quên gọi phương thức resolve() của liip_imagine.cache.manager. Nếu không, nó sẽ không xóa hình ảnh được lưu trong bộ nhớ cache của bạn.

như đã mô tả ở đây: 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

Tôi biết câu hỏi này là một chút cũ, nhưng trong trường hợp ai đó tìm kiếm một số mã (Tôi đang sử dụng SF 2.3). Tôi đã yêu cầu xóa tệp này. trong dự án của tôi, tôi đang sử dụng VichUploaderBundle để xử lý các tệp tải lên và LiipImagineBundle để xử lý tạo hình thu nhỏ cho những hình ảnh đó. Khi thực thể bị xóa, tệp đã tải lên sẽ bị xóa cũng như hình thu nhỏ (nếu có bất kỳ tệp nào được tạo). Tôi đã triển khai một trình lắng nghe học thuyết, phương thức preRemove như sau:

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

Bạn phải tạo một thực thể nghe và tạo một dịch vụ. Dịch vụ sẽ gọi cho Thực thể này mỗi sự kiện bạn muốn: tại đây trong Đăng lên và đặt trước Sản phẩm của bạn.

Trong Trình xử lý đối tượng, bạn có phương thức cho mỗi sự kiện bạn đã đặt và bạn chỉ cần xóa bộ nhớ cache trên mỗi phương thức hoặc thực hiện bất kỳ điều gì khác mà bạn muốn.

Dưới đây là một ví dụ xuất phát từ dịch vụ post

này

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 } 

Entity Listener

<?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()); 
     } 
    } 
} 

Giải pháp này hoạt động tốt trên trang web của tôi.