使用liipImagineBundle更新/删除记录时删除/更新缓存的图像


Remove/update cached image while update/delete record with liipImagineBundle

我是symfony2的新手。我正在使用liipImagineBundle来管理图像缩略图。我有一个使用生命周期回调来管理产品图像的产品实体类。

产品.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);
        }
    }
}

配置.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) }}" />
...

缩略图生成正确。

但是我无法找到在原始图像更改或删除表单时更新/删除缓存图像的方法。

您应该注册预更新和预删除事件侦听器/订阅者,注入所需的服务并删除其中的图像。

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

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

您必须创建一个侦听器实体并创建一个服务。该服务将调用此实体,每个事件您都需要:在更新后和产品的预删除中。

在实体侦听器中,您设置的每个事件都有一个方法,您只需清除每个方法上的缓存或执行所需的任何其他操作。

这里有一个例子来自这篇文章

服务

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

此解决方案在我的网站上运行良好。

不要忘记调用 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);
我知道

这个问题有点旧,但以防有人寻找一些代码(我使用的是 SF 2.3)。我对文件删除有这个要求。在我的项目中,我使用 VichUploaderBundle 来处理文件上传,使用 LiipImagineBundle 来处理这些图像的缩略图生成。删除实体时,应删除上传的文件以及缩略图(如果生成了缩略图)。我已经实现了一个原则侦听器,preRemove 方法如下:

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