2012-03-13 12 views
6

dos entidades GalleryAlbum y GalleryImage tener OneToMany/ManyToOne relación:Symfony2: PrePersist/PreUpdate ciclo de vida evento no disparó

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

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

(fuentes abajo)

¿Cuál es el problema?

  1. Adición (carga) en archivos GalleryAlbum

  2. $ em-> persist ($ álbum)

  3. $ em-> flush()

  4. Para cada archivo subido La clase GalleryAlbum crea y agrega a $ images una nueva entidad GalleryImage

  5. Mi prueba ECHO/EXIT no es t mostrado (la función de devolución de llamada del evento prePersist/preUpdate de GalleryImage llamada preUpload no se activa!)

  6. ¿Mis imágenes nuevas no se guardan en la base de datos? ¿Por qué?

¡Qué es raro!Si hago:

  1. Adición (carga) Archivos

  2. $ em-> persist ($ álbum)

  3. $ em-> flush()

  4. otra vez $ em-> flush()

  5. Se muestra mi prueba ECHO/EXIT (la función de devolución de llamada prePersist/preUpdate de GalleryImage llamada preUpload se activa)

  6. (si elimino echo/exit) ¡Mis nuevas GalleryImages se guardan ahora!

¿Por qué?

¿Por qué la precarga nunca se dispara cuando hago flush() una vez, y se dispara cuando enrojo() dos veces?

# 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; 
     } 
    } 

Respuesta

6

La primera vez que llame a persistir doctrina sólo ahorrará $ álbum y no sus imágenes. Debe especificar que desea que la doctrina de la cascada de módulos persisten especificándolo en la declaración $ imágenes:

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

De esta manera cuando se llama a persistir ($ álbum) también persistirá sus imágenes y debe dar lugar a preUpload en su GalleryImage . Hay algunas opciones diferentes disponibles para cascada y se han explicado bien aquí:

Doctrine transitive persistence cascade operations

+0

lamentablemente añadiendo cascada = { "persistir", "eliminar"} o incluso en cascada = { "todos"} no cambia nada :( – loostro

+0

Eso es extraño. Tuve el mismo problema hace unos días y esto lo solucionó. Volveré si pienso en algo más – user1207727

+0

OK, sé por qué funciona el doble flujo. Estoy creando nuevas entidades en "prePersist" "lo que significa que la doctrina ORM ya calculó qué entidades deben persistir. Por lo tanto, al invocar flush por primera vez, solo persiste el ÁLBUM. Cuando se invoca la segunda vez, la doctrina ve que persisten nuevas entidades y por eso las guarda para base de datos después de 2nd Flush. – loostro

Cuestiones relacionadas