2013-09-25 5 views
7

Ich bin neu bei symfony2. Ich benutze liipImagineBundle, um Miniaturbilder zu verwalten. Ich habe eine Product-Entity-Klasse, die Lifecycle Callbacks verwendet, um das Produktbild zu verwalten.Entferne/aktualisiere zwischengespeicherte Bilder beim Aktualisieren/Löschen von Datensätzen mit 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 } 

Thumbnail Generierungscode

... 

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

... 

Miniaturansicht-Erzeugungs korrekt.

Aber ich bin nicht in der Lage, den Weg zu finden, um zwischengespeicherte Bild zu aktualisieren/zu entfernen, während Originalbild ändern oder mit Formular löschen.

+0

Es ist nicht möglich, den Generierungscode erneut zu starten, wenn jemand das Bild über ein Formular ändert? Wie ändern sie es, indem sie ein neues Bild oder etwas hochladen? –

+0

Ich habe zwei Anforderungen 1) wenn Benutzer Produkt zu der Zeit löschen Originalbild wird gelöscht und ich möchte auch seine Miniaturansicht löschen, wenn vorhanden 2) wenn Benutzer Bild des Produkts aktualisieren, dann alte Bild sollte gelöscht werden sowie seine zwischengespeicherten Vorschaubild, wenn vorhanden –

Antwort

9

Sie sollten ein preUpdate und eine preRemove event listener/subscriber registrieren, injizieren Sie den Dienst benötigt und löschen Sie die Bilder dort.

Da Sie keinen Zugriff auf den Servicebehälter haben (und keine Services in Ihre Entitäten einfügen sollten), können Sie die Services von LiipImagineBundle nicht anfordern, um die zwischengespeicherten Dateien in Ihrer Entität mithilfe von Lifecycle-Ereignissen abzurufen.

Sie können den Dienst liip_imagine.cache.manager injizieren und die Methode remove() verwenden, um ein Bild aus dem Cache zu löschen.

2

Vergessen Sie nicht, die resolve() - Methode von liip_imagine.cache.manager aufzurufen. Andernfalls wird das zwischengespeicherte Bild nicht entfernt.

wie hier beschrieben: 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

Ich weiß, diese Frage ist ein bisschen alt, aber falls jemand sieht für einige Code (ich bin mit SF 2.3). Ich hatte diese Anforderung für die Dateientfernung. In meinem Projekt verwende ich VichUploaderBundle, um Datei-Uploads zu verarbeiten und LiipImagineBundle, um Thumbnail-Generierung für diese Bilder zu behandeln. Wenn die Entität entfernt wird, sollte die hochgeladene Datei sowie die Miniaturansicht (falls vorhanden) entfernt werden. Ich habe eine Lehre Zuhörer umgesetzt wird, ist die preremove Methode wie folgt:

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

Sie haben einen Listener Entity erstellen und einen Dienst erstellen. Der Service ruft diese Entität jedes Ereignis auf, das Sie möchten: hier im PostUpdate und in der PreRemove Ihres Produkts.

In der Entity Listener haben Sie eine Methode für jedes Ereignis, das Sie festgelegt haben, und Sie müssen nur den Cache für jede Methode löschen oder etwas anderes tun, was Sie wollen.

Hier kommt ein Beispiel aus diesem post

Dienst

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

Diese Lösung auf meiner Website gut funktioniert.

Verwandte Themen