我尝试通过doctrine / lifecycle回调实现文件上传,如下所述:
http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html#using-lifecycle-callbacks
到目前为止它可以工作,但PrePersist / PreUpdate事件没有被触发,函数“preUpload”没有被调用。 正确调用由其他生命周期事件触发的“upload”和“removeUpload”等函数。
有没有人知道为什么没有触发事件或解决这个问题?
由于
答案 0 :(得分:10)
我有另一个解决这个问题的方法:
我的实体有一个字段“updatedAt”,它是上次更新的时间戳。由于这个字段无论如何都被设置(通过Gedmo的时间戳扩展)我只是使用这个字段来欺骗教义,使其相信权利被更新了。 在我坚持实体之前,我手动设置此字段
if( $editForm['file']->getData() )
$entity->setUpdateAt(new \DateTime());
这样实体就会被持久化(因为它已经改变了),并且正确调用了preUpdate和postUpdate函数。 当然,这仅适用于您的实体具有可以像这样利用的字段。
答案 1 :(得分:6)
答案 2 :(得分: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
}
...
}
这样你就改变了一个持久化字段(这里是路径字段),所以PreUpdate()&触发PostUpdate()然后您应该在PreUpdate()函数中将路径字段值更改为您喜欢的任何内容(即时间戳),以便最终将正确的值保存到DB。
答案 3 :(得分:4)
一个技巧可能是修改实体,无论是什么...... postLoad
。
1 创建一个updatedAt
字段。
/**
* Date/Time of the update
*
* @var \Datetime
* @ORM\Column(name="updated_at", type="datetime")
*/
private $updatedAt;
2 创建一个postLoad()
函数,无论如何都会修改你的实体:
/**
* @ORM\PostLoad()
*/
public function postLoad()
{
$this->updatedAt = new \DateTime();
}
3 只需在prePersist上正确更新该字段:
/**
* @ORM\PrePersist()
* @ORM\PreUpdate()
*/
public function preUpload()
{
$this->updatedAt = new \DateTime();
//...update your picture
}
答案 4 :(得分:1)
这基本上是@ philipphoffmann回答的一个小变化: 我所做的是在持久触发preUpdate事件之前修改属性,然后在侦听器中撤消此修改:
$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()));
//...
}
}
答案 5 :(得分:0)
另一个选项是显示数据库字段,其中文件名存储为隐藏输入字段,当文件上载输入更改设置为空时,它最终触发doctrine的更新事件。所以在表单构建器中你可以有这样的东西:
->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')))
Path是由doctrine管理的属性(等于db表中的字段名称),file是处理上载的虚拟属性(不是由doctrine管理)。 css类只是将显示设置为none。然后是一个简单的js来改变隐藏输入字段的值
$('.uploader').change(function(){
var t = $(this).attr('data-target');
//clear input value
$("#"+t).val('');
});
答案 6 :(得分:0)
对我来说,当我在控制器中手动调用这些方法时,它工作得很好。
答案 7 :(得分:0)
您是否在config.yml文件中检查了元数据缓存驱动程序选项?
如果存在,只需尝试对此行进行注释:
metadata_cache_driver: whateverTheStorage
像这样:
#metadata_cache_driver: whateverTheStorage