VichUploaderBundle icon indicating copy to clipboard operation
VichUploaderBundle copied to clipboard

Upload is not performed if there is no change in the entity

Open K-Phoen opened this issue 9 years ago • 12 comments

When using doctrine, event listeners are not called if there have been no column changed. It's a problem because we precisely depend on these events to be fired to handle the uploads.

Right now, we use some boilerplate code to artificially trigger a change in the entity whenever a file is uploaded (by updating the created_at column for instance).

I'd like to find an other way to fix this issue.

K-Phoen avatar Aug 13 '14 13:08 K-Phoen

I personnaly use FormEvents to achieve this change automatically.

Example:


class ApplicationType extends AbstractType
{
...

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('icon', 'file', array(
                'required' => false,
            ));

        $builder->get('icon')->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $e){
            if(!empty($e->getData())){
                /** @var Application $app */
                $app = $e->getForm()->getParent()->getData();
                $app->setUpdateAt(new \DateTime());
            }
        });
    }

...
}

This code simply checks if the icon field has data. Then, updates the target entity if needed.

I guess it will be possible to consider the creation of a dedicated form type vich_file or else, which would be responsible for update a user configurable entity field via the field options form. These option could be named update_property for instance.

Another and complementary form type could also check if the form entity implements a given interface, in charge to update the updatedAt field when the interface method is called. Therefore, no more configuration is needed from user.

ogizanagi avatar Aug 14 '14 10:08 ogizanagi

The thing is I don't want to rely on this kind of "hack". We should not have to ask the user to write boilerplate code/implement an interface/add a "updated at" field.

K-Phoen avatar Aug 14 '14 16:08 K-Phoen

if we use update date in entity setter as in example

public function setImageFile(File $image = null)
{
    $this->imageFile = $image;

    if ($image) {
        // It is required that at least one field changes if you are using doctrine
        // otherwise the event listeners won't be called and the file is lost
        $this->updatedAt = new \DateTime('now');
    }
}

this is execute in each time where entity is loaded. if after call $em->flush() updatedAt field will be updated in db - one query for each entity. it generate 1000+ queries in my db in some controllers where many entities loaded and call "flush".

rik43 avatar Mar 25 '15 15:03 rik43

@rik43 you must check if File is an UploadedFile. See https://github.com/dustin10/VichUploaderBundle/issues/8#issuecomment-3780172

garak avatar Apr 22 '15 08:04 garak

good idea, thanks

rik43 avatar Apr 22 '15 08:04 rik43

Is there a chance you fix this issue one day ?

Reproduced using :

  • vich/uploader-bundle : 1.16.0
  • symfony : 5.0.11
  • php : 7.4.13

acantepie avatar Dec 12 '20 21:12 acantepie

Is there a chance you fix this issue one day ?

This is the wrong question. The right question is: is there a chance we fix this issue one day?

garak avatar Dec 13 '20 13:12 garak

Ok, but this issue was opened 5 years ago...

I you (we) don't manage to fix it, maybe you (we) should change this part of documentation :

    /**
     * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
     * of 'UploadedFile' is injected into this setter to trigger the update. If this
     * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
     * must be able to accept an instance of 'File' as the bundle will inject one here
     * during Doctrine hydration.
     *
     * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile|null $imageFile
     */

acantepie avatar Dec 13 '20 13:12 acantepie

@acantepie it's already documented just 4 lines after

garak avatar Dec 13 '20 17:12 garak

just ran into this issue.

bundle version: 1.19.1 symfony version: 5.4.8

wanting to add in that if the update/created blamable/timestampable values are managed by something like doctrine extensions, that is not enough to trigger the uploader/clean-listener.

ended up making a "dummy" column in the table to just always update as part of the request processing

$formAttachment->setMetadata(uniqid('kittens', true));

chancegarcia avatar May 20 '22 05:05 chancegarcia

wanting to add in that if the update/created blamable/timestampable values are managed by something like doctrine extensions, that is not enough to trigger the uploader/clean-listener.

That's probably a matter of priority in Doctrine listeners

garak avatar May 20 '22 06:05 garak

Hi, I want to add a comment after having been through the issue of file not uploaded for new entity. It may affect you if you're using translatable in any of the field on the entity. After further checking it seems that translatable will trigger a persist early on the form lifecycle (the $form->handleRequest() call) with the uploaded file not being set on the entity yet. And when I call $entityManager->persist($object) the prePersist code from this bundle will not be called (I assume because it have been called in the handleRequest() call. So what I do is I add the code $uploadHandler->upload($object, 'file') before $entityManager->persist($object) to trigger it manually. Of course these only works if you're in the same situation like me. Just for reference for others. Thanks!

sudent avatar Dec 07 '22 10:12 sudent