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