2013-09-25 6 views
7

Jestem nowy w symfony2. Używam liipImagineBundle do zarządzania miniaturą obrazu. Mam klasy encji produktu, która używa wywołań zwrotnych cyklu życia do zarządzania obrazem produktu.Usuń/zaktualizuj buforowany obraz podczas aktualizacji/usuwania rekordu za pomocą 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 } 

kod generowanie miniatur

... 

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

... 

generowanie miniatur poprawnie.

Ale nie jestem w stanie znaleźć sposobu na aktualizację/usunięcie obrazu z pamięci podręcznej podczas zmiany oryginalnego obrazu lub usunięcia go za pomocą formularza.

+0

Nie można ponownie uruchomić kodu generacyjnego, gdy ktoś zmieni obraz za pomocą formularza? Jak to zmienić, przesyłając nowy obraz lub coś takiego? –

+0

Mam dwa wymagania: 1) gdy użytkownik usunie produkt w momencie, gdy oryginalny obraz zostanie usunięty i ja również chcę usunąć jego miniaturkę jeśli istnieje 2) gdy obraz aktualizacji produktu użytkownika powinien zostać usunięty, a także jego buforowany obraz miniatura, jeśli istnieje –

Odpowiedz

9

Należy zarejestrować preUpdate i preRemove event listener/subscriber, wprowadzić wymaganą usługę i usunąć tam obrazy.

Ponieważ nie masz dostępu do kontenera usług (i nie powinieneś wstrzykiwać usług do twoich jednostek), nie możesz przesyłać zapytań do usług LiipImagineBundle w celu uzyskania buforowanych plików z wnętrza twojego obiektu za pomocą Lifecycle Events.

Można wprowadzić usługę liip_imagine.cache.manager i użyć jej metody remove(), aby usunąć obraz z pamięci podręcznej.

2

Nie zapomnij wywołać metody resolve() z liip_imagine.cache.manager. W przeciwnym razie nie usunie obrazu z pamięci podręcznej.

jak opisano tutaj: 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

Wiem, że to pytanie jest nieco stary, ale w przypadku, gdy ktoś szuka jakiegoś kodu (używam SF 2.3). Miałem ten wymóg usuwania plików. w moim projekcie używam VichUploaderBundle do obsługi przesyłania plików i LiipImagineBundle do obsługi generowania miniatur dla tych obrazów. Po usunięciu elementu należy usunąć przesłany plik, a także miniaturę (jeśli została wygenerowana). I zostały wdrożone słuchacza doktrynie metoda preRemove jest następująca:

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

Musisz utworzyć słuchacz jednostki i stworzyć usługę. Usługa będzie wywoływać tę jednostkę dla każdego zdarzenia, które chcesz: tutaj w PostUpdate i preRemove produktu.

W odbiorniku jednostki masz metodę dla każdego ustawionego zdarzenia i musisz wyczyścić pamięć podręczną każdej metody lub zrobić cokolwiek innego.

Oto przykład pochodzi z tego post

Służby

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 } 

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

to rozwiązanie działa dobrze na moim miejscu.

Powiązane problemy