2012-03-13 13 views
6

due entità GalleryAlbum e GalleryImage avere OneToMany/ManyToOne relazione:Symfony2: PrePersist/PreUpdate ciclo di vita-evento non ha sparato

One GalleryAlbum ==== can have ====> Many GalleryImage

Many GalleryImage === can be in ===> One GalleryAlbum

(fonti sotto)

Qual è il problema?

  1. Aggiunta di file (upload) a GalleryAlbum

  2. $ em-> persist ($ album)

  3. $ em-> a filo()

  4. Per ogni file caricato La classe GalleryAlbum crea e aggiunge a $ images una nuova entità GalleryImage

  5. Il mio test ECHO/EXIT è no t mostrato (la funzione di callback dell'evento prePersist/preUpdate di GalleryImage denominata preUpload non viene attivata!)

  6. Le mie nuove immagini non vengono salvate nel database? Perché?

Che cosa è strano!Se faccio:

  1. Aggiunta (upload) file

  2. $ em-> persist ($ album)

  3. $ em-> flush()

  4. again $ em-> flush()

  5. Il mio test ECHO/EXIT è mostrato (la funzione di callback prePersist/preUpdate dell'evento denominata preUpload è attivata!)

  6. (se cancello echo/exit) Le mie nuove GalleryImages vengono salvate ora !!!

Perché?

Perché preUpload non viene mai attivato quando si scarica() una volta e viene attivato quando si esegue il flush() due volte?

# src GalleryAlbum.php

 
    /** 
    * @ORM\Entity 
    * @ORM\HasLifecycleCallbacks 
    * @ORM\Table(name="gallery_album") 
    */ 
    class GalleryAlbum 
    { 
     // some properties like id, name, description, etc 

     /** 
     * @ORM\OneToMany(targetEntity="GalleryImage", mappedBy="parent") 
     */ 
     protected $images; 

     /* Files container. Used for upload service. Must not be persisted. */ 

     protected $files;  

     /* @ORM\Column(type="boolean", nullable=TRUE) 
     * 
     * if set to true will updateing object and calling preUpdate event callback 
     * becouse it's always set to null in database by prePersist event callback */ 

     protected $files_added; 

     /** 
     * Set container files 
     * 
     * @return GalleryAlbum 
     */ 
     public function setFiles($files) 
     { 
      $this->files = $files; 
      $this->files_added = true; 
      /* setting files_added to true forces EntityManager to update 
       * this GalleryAlbum even if no other properties have changed */ 

      return $this; 
     } 

     /** 
     * @ORM\PrePersist() 
     * @ORM\PreUpdate() 
     */ 
     public function preUpload() 
     { 
      if(null !== $this->files) { 
       foreach($this->files as $key =>$file) { 
        $this->addGalleryElement($file); 
        unset($this->files[$key]); 
       } 
      } 
      /* Resetting property files_added to NULL 
      * so it always stays null in database */ 
      $this->files_added = null; 
     } 


     /** 
     * Constructing new GalleryImage and setting it's file and parent 
     */ 
     public function addGalleryElement($file) 
     {  
      $element = new GalleryImage($this, $file); 
      $this->addGalleryImage($element); 
     } 
    } 

# src GalleryImage.php

 
    /** 
    * @ORM\Entity 
    * @ORM\HasLifecycleCallbacks 
    * @ORM\Table(name="gallery_image") 
    */ 
    class GalleryImage 
    { 
     // some properties like id, name, description, etc 

     /** 
     * @ORM\ManyToOne(targetEntity="GalleryAlbum", inversedBy="images") 
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id") 
     */ 
     protected $parent; 

     /* Constructing new GalleryImage */ 

     public function __construct($parent = null, $file = null) 
     { 
      if($parent) $this->setParent($parent); 
      if($file) $this->setFile($file);  
     } 

     /** 
     * @ORM\PrePersist() 
     * @ORM\PreUpdate() 
     */ 
     public function preUpload() 
     { 
      echo 'TEST: is this event callback function fired?'; exit; 

      if(null !== $this->file) { 
       $this->path = $this->file->guessExtension(); 
      } 

      $this->file_added = null; 
     } 
    } 

risposta

6

La prima volta che si chiama persistere dottrina salverà solo $ album e non le sue immagini. È necessario specificare che si desidera dottrina a cascata il persistere specificando che nella dichiarazione $ immagini:

/** 
    * @ORM\OneToMany(targetEntity="GalleryImage", mappedBy="parent", cascade={"persist", "remove"}) 
    */ 
    protected $images; 

In questo modo quando si chiama persistono ($ album) sarà anche persistere le immagini e dovrebbe innescare preUpload nel vostro GalleryImage . Ci sono alcune opzioni differenti disponibili per cascata e sono spiegati bene qui:

Doctrine transitive persistence cascade operations

+0

purtroppo aggiungendo cascade = { "persistere", "rimuovere"} o anche cascade = { "tutti"} non cambia nulla :( – loostro

+0

Questo è strano, ho avuto lo stesso problema qualche giorno fa e questo ha risolto il problema per me.Tornerò se penso a qualsiasi altra cosa – user1207727

+0

OK so perché il doppio flush funziona. Sto creando nuove Entità in "prePersist" "Ciò significa che la dottrina ORM ha già calcolato quali entità devono essere persistenti, quindi quando si chiama flush per la prima volta - viene mantenuto solo ALBUM. Quando lo si chiama la seconda volta la dottrina vede persistere le nuove entità e questo è il motivo per cui le salva in database dopo 2nd flush. – loostro

Problemi correlati