Vichuploaderbundle: Delete checkbox only removes filename from entity

Created on 7 Feb 2016  路  6Comments  路  Source: dustin10/VichUploaderBundle

I just installed VichUploader 1.0.0.-beta 7 for Symfony 2.8.2 and to avoid writing a manual delete script I want to use the delete checkbox for the Vich form type.

However, when I select the Delete checkbox and press on Update (I am updating the Note entity with a OneToMany relation with Attachment) the Attachment entity is not completely deleted. The file is deleted, the fileName property is empty (not NULL), but the id fields and the updatedAt fields are still there.

Because the Attachment entity isn't deleted, the links are still there (to non existing files).

Is this how it supposes to work or have I misconfigured anything?

This is my FormType for Note:

$builder
            ->add('body', null, array(
                'label' => 'notes.body',
            ))
            ->add('attachments', CollectionType::class, array(
                'label' => 'notes.attachment',
                'entry_type' => NoteAttachmentType::class,
                'allow_add'    => true,
                'allow_delete' => true,
                'by_reference' => false,
            ))
        ;

and my NoteAttachmentType:

 public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('file', VichFileType::class, array(
            'required'      => false,
            'allow_delete'  => true, // not mandatory, default is true
            'download_link' => true, // not mandatory, default is true
        ));
    }
Support

Most helpful comment

I know this question is a few months old, but for those who want their file entity removed when the file is deleted (like me), you can register a simple event listener to take care of that.

In your services.yml:

app_bundle.listener.removed_file_listener:
        class: AppBundle\EventListener\RemovedFileListener
        arguments: [@doctrine.orm.entity_manager]
        tags:
            - { name: kernel.event_listener, event: vich_uploader.post_remove, method: onPostRemove }

And the listener:

namespace AppBundle\EventListener;

use Vich\UploaderBundle\Event\Event;

class RemovedFileListener
{
    /**
     *
     * @param \Doctrine\ORM\EntityManager $em
     */
    public function __construct(\Doctrine\ORM\EntityManager $em)
    {
        $this->em = $em;
    }

    // make sure a file entity object is removed after the file is deleted
    public function onPostRemove(Event $event)
    {
        // get the file object
        $removedFile = $event->getObject();
        // remove the file object from the database
        $this->em->remove($removedFile);
        $this->em->flush();
    }
}

All 6 comments

Have the same problem here, did you solve this ?

VichUploaderBundle does not remove entities, you need to remove them yourself. Or, you probably have a minor relation problem somewhere that does not _persist_ the relation removal.

But I don't get the usefulness of this code then:

    // Handler/UploadHandler.php
    public function remove($obj, $fieldName)
    {
        $mapping = $this->getMapping($obj, $fieldName);
        $oldFilename = $mapping->getFileName($obj);

        // nothing to remove, avoid dispatching useless events
        if (empty($oldFilename)) {
            return;
        }

        $this->dispatch(Events::PRE_REMOVE, new Event($obj, $mapping));

        $this->storage->remove($obj, $mapping);
        $mapping->setFileName($obj, null);

        $this->dispatch(Events::POST_REMOVE, new Event($obj, $mapping));
    }

Both options allow_delete and download_link on VichFileType types only deal with files not entities. Entities should be remove normally with for example $notes->removeAttachement($attachement).

The allow_delete option on CollectionType on the other hand deals with deleting collection elements.

Just keep in mind that this bundle, is a file upload bundle, nothing more, it does not, and should not deal with your entities.

To put it simple, you can have an entity with a file attribute that is not mandatory, like an email with attachment. You can delete the attachment with vichuploader but keep the email, if you want to delete the email, you need to use doctrine for example.

I know this question is a few months old, but for those who want their file entity removed when the file is deleted (like me), you can register a simple event listener to take care of that.

In your services.yml:

app_bundle.listener.removed_file_listener:
        class: AppBundle\EventListener\RemovedFileListener
        arguments: [@doctrine.orm.entity_manager]
        tags:
            - { name: kernel.event_listener, event: vich_uploader.post_remove, method: onPostRemove }

And the listener:

namespace AppBundle\EventListener;

use Vich\UploaderBundle\Event\Event;

class RemovedFileListener
{
    /**
     *
     * @param \Doctrine\ORM\EntityManager $em
     */
    public function __construct(\Doctrine\ORM\EntityManager $em)
    {
        $this->em = $em;
    }

    // make sure a file entity object is removed after the file is deleted
    public function onPostRemove(Event $event)
    {
        // get the file object
        $removedFile = $event->getObject();
        // remove the file object from the database
        $this->em->remove($removedFile);
        $this->em->flush();
    }
}

I consider this resolved with last suggestion.

Was this page helpful?
0 / 5 - 0 ratings