2011-09-05 18 views
2

我試圖實現通過主義/生命週期回調的文件上傳如下所述:到目前爲止,它的工作原理Symfony2的:通過學說文件上傳不火的PrePersist /更新前的生命週期事件

http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html#using-lifecycle-callbacks

,但PrePersist/PreUpdate事件未被觸發,函數「preUpload」未被調用。 正確調用其他生命週期事件觸發的「upload」和「removeUpload」等功能。

有沒有人有一個想法,爲什麼事件沒有解僱或解決這個問題?

感謝

回答

0

另一種選擇是顯示在文件名存儲爲一個隱藏的輸入字段,並在文件上傳輸入改變設置,爲數據庫字段因此它最終會觸發教義的更新事件。因此,在表單生成器,你可以有這樣的事情:

->add('path', 'text', array('required' => false,'label' => 'Photo file name', 'attr' => array('class' => 'invisible'))) 
->add('file', 'file', array('label' => 'Photo', 'attr' => array('class' => 'uploader','data-target' => 'iddp_rorschachbundle_institutiontype_path'))) 

路徑是通過主義(等於字段名在數據庫表)管理的財產和文件是虛擬財產來處理上傳(不管理教義)。 CSS類簡單地將顯示設置爲無。然後,一個簡單的JS改變隱藏的輸入字段

$('.uploader').change(function(){ 
     var t = $(this).attr('data-target'); 
     //clear input value 
     $("#"+t).val(''); 
}); 
10

我還有另外一個解決這個問題的價值:

我的實體有一個字段「updatedAt」,這是最後一次更新的時間戳。由於無論如何都會設置此字段(通過Gedmo的時間戳擴展),我只是使用該字段欺騙教條,使其相信該實體已更新。 之前,我堅持我把這個字段設置實體人工手動操作

if($editForm['file']->getData()) 
    $entity->setUpdateAt(new \DateTime()); 

這樣的實體被持久化(因爲它已經改變),更新前和postUpdate功能得到正確調用。 當然,這隻有在你的實體有一個你可以利用的領域時纔有效。

+0

我喜歡這一個欺騙主義。 – insertusernamehere

+0

我已經提出了與實體中的邏輯類似的解決方案。感謝這個想法@philipphoffmann – Mick

4

不斷變化的跟蹤政策和其他解決方案相比有一個更簡單的解決方案:

在控制器:

if ($form->isValid()) { 
    ... 
    if ($form->get('file')->getData() != NULL) {//user have uploaded a new file 
     $file = $form->get('file')->getData();//get 'UploadedFile' object 
     $news->setPath($file->getClientOriginalName());//change field that holds file's path in db to a temporary value,i.e original file name uploaded by user 
    } 
    ... 
} 

這種方式,你已經改變了持久場(這裏是路場),所以更新前()& PostUpdate()被觸發,那麼你應該在PreUpdate()函數中將路徑字段值更改爲任何你喜歡的東西(即時間戳),因此最終正確的值被持久化爲DB。

4

一個竅門可能是修改實體,不管是什麼..在postLoad


創建updatedAt場。

/** 
* Date/Time of the update 
* 
* @var \Datetime 
* @ORM\Column(name="updated_at", type="datetime") 
*/ 
private $updatedAt; 

創建postLoad()函數,將反正修改您的實體:

/** 
* @ORM\PostLoad() 
*/ 
public function postLoad() 
{ 
    $this->updatedAt = new \DateTime(); 
} 

只是正確地更新prePersist那場:

/** 
* @ORM\PrePersist() 
* @ORM\PreUpdate() 
*/ 
public function preUpload() 
{ 
    $this->updatedAt = new \DateTime(); 
    //...update your picture 
} 
+0

完美的作品適合我,謝謝 – loicfavory

0

對我來說,當我在控制器中手動調用這些方法時工作得很好。

0

您是否在config.yml文件中檢查了您的元數據緩存驅動程序選項?
如果它存在,只是試評這一行:

metadata_cache_driver: whateverTheStorage 

像這樣:

#metadata_cache_driver: whateverTheStorage 
1

這基本上是@ philipphoffmann的回答略有變化: 我做什麼,我修改屬性堅持以觸發更新前的事件發生前,然後我撤消聽者這個修改:

$entity->setToken($entity->getToken()."_tmp"); 
$em->flush(); 

在我的聽衆:

public function preUpdate(LifecycleEventArgs $args) 
{ 
    $entity = $args->getEntity(); 

    if ($entity instanceof MyEntity) { 
     $entity->setToken(str_replace('_tmp', '', $entity->getToken())); 
     //... 
    } 
} 
相關問題