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

时间:2013-09-25 06:41:38

标签: php symfony liipimaginebundle

我是symfony2的新手。 我正在使用liipImagineBundle来管理图像缩略图。 我有一个产品实体类,它使用Lifecycle Callbacks来管理产品图像。

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

...

缩略图正确生成。

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

4 个答案:

答案 0 :(得分:9)

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

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

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

答案 1 :(得分:3)

您必须创建一个侦听器实体并创建一个服务。 该服务将在每个事件中调用此实体:在PostUpdate和产品的preRemove中。

在Entity Listener中,您为已设置的每个事件都有一个方法,您只需清除每个方法的缓存或执行您想要的任何其他操作。

此处的示例来自此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());
        }
    }
}

此解决方案在我的网站上正常运行。

答案 2 :(得分: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);

答案 3 :(得分:2)

我知道这个问题有点旧,但万一有人找一些代码(我使用的是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);
    }
}