Reputation: 75
i tried to implement the file upload via doctrine/lifecycle callbacks as described here:
http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html#using-lifecycle-callbacks
So far it works, but the PrePersist/PreUpdate Event is not fired, the function "preUpload" is not called. Functions like "upload" and "removeUpload" triggered by other lifecycle events are called correctly.
Does anyone have an idea why the event is not fired or a solution for this problem?
Thanks
Upvotes: 2
Views: 7110
Reputation: 1043
This is basically a slight variation of @philipphoffmann's answer: What i do is that i modify an attribute before persisting to trigger the preUpdate event, then i undo this modification in the listener:
$entity->setToken($entity->getToken()."_tmp");
$em->flush();
In my listener:
public function preUpdate(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if ($entity instanceof MyEntity) {
$entity->setToken(str_replace('_tmp', '', $entity->getToken()));
//...
}
}
Upvotes: 1
Reputation: 218
Do you have checked your metadata cache driver option in your config.yml file?
If it exists, just try to comment this line:
metadata_cache_driver: whateverTheStorage
Like this:
#metadata_cache_driver: whateverTheStorage
Upvotes: 0
Reputation: 1623
For me, it worked good when I just manually called these methods in the controller.
Upvotes: 0
Reputation: 31949
A trick could be to modify the entity no matter what..on postLoad
.
1 Create an updatedAt
field.
/**
* Date/Time of the update
*
* @var \Datetime
* @ORM\Column(name="updated_at", type="datetime")
*/
private $updatedAt;
2 Create a postLoad()
function that will modify your entity anyway:
/**
* @ORM\PostLoad()
*/
public function postLoad()
{
$this->updatedAt = new \DateTime();
}
3 Just update that field correctly on prePersist:
/**
* @ORM\PrePersist()
* @ORM\PreUpdate()
*/
public function preUpload()
{
$this->updatedAt = new \DateTime();
//...update your picture
}
Upvotes: 4
Reputation: 5749
there's a much simpler solution compared with changing tracking policies and other solutions:
in controller:
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
}
...
}
this way you have changed a persisted field (here it is path field), so PreUpdate() & PostUpdate() are triggered then you should change path field value to any thing you like (i.e timestamp) in PreUpdate() function so in the end correct value is persisted to DB.
Upvotes: 4
Reputation: 785
I have another solution to this problem:
My entity has a field "updatedAt" which is a timestamp of the last update. Since this field gets set anyway (by the timestampable extension of Gedmo) I just use this field to trick doctrine into believing that the entitiy was updated. Before I persist the entity I set this field manually doing
if( $editForm['file']->getData() )
$entity->setUpdateAt(new \DateTime());
This way the entity gets persisted (because it has changed) and the preUpdate and postUpdate functions are called properly. Of course this only works if your entity has a field that you can exploit like that.
Upvotes: 10
Reputation: 10706
Another option is to display the database field where the filename is stored as a hidden input field and when the file upload input changes set that to empty so it ends up triggering doctrine's update events. So in the form builder you could have something like this:
->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 is a property managed by doctrine (equal to the field name in the db table) and file is the virtual property to handle uploads (not managed by doctrine). The css class simply sets the display to none. And then a simple js to change the value of the hidden input field
$('.uploader').change(function(){
var t = $(this).attr('data-target');
//clear input value
$("#"+t).val('');
});
Upvotes: 0