Php Symfony 4-LiipImagine-Listener删除所有我的目录(缓存清除侦听器)

Php Symfony 4-LiipImagine-Listener删除所有我的目录(缓存清除侦听器),php,symfony,caching,listener,liipimaginebundle,Php,Symfony,Caching,Listener,Liipimaginebundle,我有一个symfony 4项目,其中一个用户实体与一个化身实体有关系(使用VichUploaderBundle上传的图像) 在Avatar.php中: /** * @ORM\Column(type="string", length=255, nullable=true) */ private $imageName; /** * NOTE: This is not a mapped field of entity metadata, just a simple property. *

我有一个symfony 4项目,其中一个用户实体与一个化身实体有关系(使用VichUploaderBundle上传的图像)

在Avatar.php中:

/**
 * @ORM\Column(type="string", length=255, nullable=true)
 */
private $imageName;

/**
 * NOTE: This is not a mapped field of entity metadata, just a simple property.
 * 
 * @Assert\Image(
 *  mimeTypes="image/jpeg")
 * @Vich\UploadableField(mapping="avatar", fileNameProperty="imageName", size="imageSize")
 * 
 * @var File|null
 */
private $imageFile;
/**
 * @ORM\OneToOne(targetEntity="App\Entity\Avatar", mappedBy="user", cascade={"persist", "remove"})
 */
private $avatar;
  App\Listener\ImageCacheSubscriber:
    tags:
      - { name: doctrine.event_subscriber }
在User.php中:

/**
 * @ORM\Column(type="string", length=255, nullable=true)
 */
private $imageName;

/**
 * NOTE: This is not a mapped field of entity metadata, just a simple property.
 * 
 * @Assert\Image(
 *  mimeTypes="image/jpeg")
 * @Vich\UploadableField(mapping="avatar", fileNameProperty="imageName", size="imageSize")
 * 
 * @var File|null
 */
private $imageFile;
/**
 * @ORM\OneToOne(targetEntity="App\Entity\Avatar", mappedBy="user", cascade={"persist", "remove"})
 */
private $avatar;
  App\Listener\ImageCacheSubscriber:
    tags:
      - { name: doctrine.event_subscriber }
我有一个个人资料页面来编辑用户的数据(姓名、姓氏、邮件、头像)。 在这个页面中,我使用LiipImagineBundle以特定的维度显示当前的化身

当用户编辑他的个人资料时,我希望听众能检查一下头像是否有变化。在这种情况下,它会删除旧媒体/缓存

所以我为它创建了一个监听器:

<?php

namespace App\Listener;

use App\Entity\Avatar;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;

class ImageCacheSubscriber implements EventSubscriber
{

    /**
     * CacheManager
     *
     * @var CacheManager
     */
    private $cacheManager;

    /**
     * UploaderHelper
     *
     * @var UploaderHelper
     */
    private $uploaderHelper;

    public function __construct(CacheManager $cacheManager, UploaderHelper $uploaderHelper)
    {
        $this->cacheManager = $cacheManager;
        $this->uploaderHelper = $uploaderHelper;
    }

    public function getSubscribedEvents()
    {
        return [
            'preRemove',
            'preUpdate'
        ];
    }

    public function preRemove(LifecycleEventArgs $args)
    {

        $entity = $args->getEntity();
        if (!$entity instanceof Avatar) {
            return;
        }

        $this->cacheManager->remove($this->uploaderHelper->asset($entity, 'imageFile'));
    }

    public function preUpdate(PreUpdateEventArgs $args)
    {
        dump($args->getEntity());
        dump($args->getObject());

        $entity = $args->getEntity();
        if (!$entity instanceof Avatar) {
            return;
        }

        if ($entity->getImageFile() instanceof UploadedFile) {
            $this->cacheManager->remove($this->uploaderHelper->asset($entity, 'imageFile'));
        }
    }
}
但是,当我更改我的化身时,侦听器会删除媒体中包含化身的整个文件夹

他挑起我这个错误:

无法删除目录 “C:\Users\user\Desktop\churchest2/public/media/cache/avatar\u big\files”: rmdir(C:\Users\user\Desktop\consuccess2/public/media/cache/avatar\u big\files): 目录不为空

我不明白为什么……:'(

编辑:

我将函数preUpdate()更新为postUpdate():

现在,如果我说:

    dd($this->uploaderHelper->asset($entity, 'imageFile'));
我已经:

“/images/avatar/avatar3.jpg” 这是一条很好的路径!另一方面,图像没有从缓存中删除!remove()函数似乎没有给出任何令人惊奇的结果

随着实体的转储,我看到文件不再是一个UploadedFile,而是一个简单的文件。而以前它看起来像一个UploadedFile。所以我更改了行

if ($entity->getImageFile() instanceof UploadedFile)

但是图像仍然没有从缓存中删除


在我看来,由于这是一个假定更新,它会删除新的缓存映像,而不是旧的。但是由于用户被重定向到同一个页面,他会在缓存后立即交付它。(编辑:否,我做了一个测试,映像甚至没有从缓存中删除)

在使用VichUploaderBundle时,不需要创建自己的侦听器。请确保正确配置了生命周期事件,并且Vich应负责删除旧映像

# config/packages/vich_uploader.yaml or app/config/config.yml
vich_uploader:
    db_driver: orm
    mappings:
        product_image:
            uri_prefix: /images/products
            upload_destination: '%kernel.project_dir%/public/images/products'

            inject_on_load: false
            delete_on_update: true
            delete_on_remove: true

您可以收听
vich_uploader.pre_remove
事件,而不是收听Doctrine事件。这将确保您每次都能获得需要删除的旧映像。首先,确保您的VichUploader配置设置为更新和删除时删除文件。这是默认设置

# config/packages/vich_uploader.yaml

vich_uploader:
    mappings:
        avatar:
            upload_destination: '%kernel.project_dir%/public/uploads/avatar'
            uri_prefix: 'uploads/avatar'

            delete_on_update: true
            delete_on_remove: true
现在需要创建侦听器

//src/EventListener/ImageCacheSubscriber.php
名称空间App\EventListener;
使用Liip\ImagineBundle\Imagine\Cache\CacheManager;
使用Symfony\Component\EventDispatcher\EventSubscriberInterface;
使用Vich\UploaderBundle\Event\Event;
使用Vich\UploaderBundle\Event\Events;
使用Vich\UploaderBundle\Storage\StorageInterface;
类ImageCacheSubscriber实现EventSubscriberInterface
{
私人储存;;
私人经理;
公共函数构造(StorageInterface$storage,CacheManager$CacheManager)
{
$this->storage=$storage;
$this->cacheManager=$cacheManager;
}
公共函数onRemove(事件$Event)
{
$path=$this->storage->resolveUri($event->getObject(),$event->getMapping()->getFilePropertyName());
$this->cacheManager->remove($path);
}
公共静态函数getSubscribedEvents()
{
return[Events::PRE_REMOVE=>onRemove'];
}
}
删除任何VichUploader资产时,此侦听器将尝试将其从所有筛选器的缓存中删除。如果愿意,您可以在
CacheManager::remove()
方法中指定特定筛选器。您也只能通过检查
$event->getObject()
的实例来删除特定实体的缓存

这还对LiipMagine配置进行了一些假设。如果您使用的是默认加载程序和缓存解析程序,则应该可以使用。如果您使用的是自定义加载程序或解析程序,则可能需要根据需要修改此侦听器

# config/packages/liip_imagine.yaml

liip_imagine:
    resolvers:
        default:
            web_path:
                web_root: '%kernel.project_dir%/public'
                cache_prefix: 'media/cache'

    loaders:
        default:
            filesystem:
                data_root:
                    - '%kernel.project_dir%/public'

    filter_sets:
        cache: ~

        # Your filters...
如果您使用的是symfonyflex,那么就完成了。否则,请确保将侦听器注册为服务

# config/services.yaml

services:
    # ...
    App\EventListener\ImageCacheSubscriber:
        arguments: ['@vich_uploader.storage.file_system', '@liip_imagine.cache.manager']
        tags:
            - { name: kernel.event_subscriber }

这不是问题,如果我删除或更新一个图像,它将在包含我的文件的目录中更新。但问题出在LiipMagineBundle上。缓存的图像不是deletedOk my bad,$this->uploaderHelper->asset($entity,'imageFile')的输出是什么?$entity,'imageFile')哇!它返回“null”。奇怪的是,如果我转储($entity),我的“Avatar”实体您可能想先查看一下,也许您的Vich配置已关闭?通常情况下,我的VichUploader配置不可用。更新时删除和删除时删除都可以,所以应该没有问题哇,非常感谢,它似乎工作得很好!