Vichuploaderbundle: Files in collection are nulled when updating entity

Created on 19 Oct 2017  路  29Comments  路  Source: dustin10/VichUploaderBundle

  • "symfony/symfony": "3.3.*"
  • "sonata-project/admin-bundle": "3.23.0"
  • "vich/uploader-bundle": "1.6.2"

I'm adding image upload in SonataAdminBundle. Images are multiple, so collection is used. I've implemented exactly the same code, I've used with Symfony 2.8 and VichUploadBundle 1.4, and everything works the same (fine), except for:

  1. When I create new or open existing entity
  2. I either see uploaded image for existing entity or can upload one for new entity, save and see uploaded image after refresh.
  3. When I press "update" (without even changing a single value) again
  4. Edit view refreshes, but uploaded images are gone (also in database)

So, collection of uploaded files is reset/nulled after updating entity.

My code:
```php
// Product:

/**

  • @ORM\Entity
    /
    class Product
    {
    /
    *

    • @ORM\ManyToMany(

    • targetEntity="Image",

    • cascade={"persist", "remove"},

    • orphanRemoval=true

    • )

    • @ORM\JoinTable(

    • name="product_image",

    • joinColumns={@ORM\JoinColumn},

    • inverseJoinColumns={@ORM\JoinColumn}

    • )

      */

      protected $images;

public function __construct()
{
    $this->images = new ArrayCollection();
}

public function getImages()
{
    return $this->images;
}

public function setImages(Collection $images)
{
    $this->images = $images;
}

public function addImage(Image $image)
{
    if ( ! $this->images->contains($image)) {
        $this->images->add($image);
    }
}

public function removeImage(Image $image)
{
    if ($this->images->contains($image)) {
        $this->images->removeElement($image);
    }
}

}

// Image:

/**

  • @ORM\Entity
  • @Vich\Uploadable
    /
    class Image
    {
    /
    *

    • @Vich\UploadableField(mapping="image", fileNameProperty="filename")

      *

    • @var \Symfony\Component\HttpFoundation\File\File|null

      */

      private $file;

/**
 * @ORM\Column(type="string")
 *
 * @var string
 */
private $filename;

/**
 * @ORM\Column(type="datetime")
 *
 * @var \DateTime
 */
private $updatedAt;

public function getFile()
{
    return $this->file;
}

public function setFile(\Symfony\Component\HttpFoundation\File\File $file = null)
{
    $this->file = $file;

    if ($file !== null) {
        $this->updatedAt = new \DateTime('now');
    }
}

public function getFilename()
{
    return $this->filename;
}

public function setFilename($filename)
{
    $this->filename = $filename;
}

}

// ProductAdmin:
class ProductAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('images', 'collection', [
'entry_type' => UploadedImageType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
]);
}
}

// UploadedImageType:
class UploadedImageType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('file', VichImageType::class, [
'label' => false,
'required' => false,
]);
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'data_class' => Image::class,
    ]);
}

}

Support

Most helpful comment

garak, I have created the project where it shows the bug.

https://github.com/skornev/vichbundle-sandbox-not-cp-symfony3.3

All 29 comments

I'm sorry but I don't use Sonata.
Please try to reproduce the issue without Sonata.

I have the same issue On Symfony 3.3 and vich/uploader-bundle 1.6.2. I don't use Sonata.
Attachments collection is just empty.

The problem is with VichFileType and Symfony 3.3

Used to work but now it does not

$builder ->add('file', VichFileType::class, array( 'required' => false, 'allow_delete' => false, // not mandatory, default is true 'download_uri' => true, // not mandatory, default is true 'download_label' => true ));
A quick way to fix that issue. If we add a text field now it works.

$builder ->add('originalName', TextType::class, [ 'required' => false ]) ->add('file', VichFileType::class, array( 'required' => false, 'allow_delete' => false, // not mandatory, default is true 'download_uri' => true, // not mandatory, default is true 'download_label' => true ));

Please create a basic Symfony project where it's possible to reproduce the issue.

I have some similar issue without using Sonata. I can create my entity with an VIchUploader image collection, but I can't edit it (nor I can display the existing images in my edition template).

garak, I have created the project where it shows the bug.

https://github.com/skornev/vichbundle-sandbox-not-cp-symfony3.3

Fixed. Please, try again.

I have the same issue.
Symfony 3.3.10
VichUploaderBundle 1.4.2

I'd say that is an expected behavior, since you're using orphanRemoval=true and when you update, the collection of attachments is empty (this is also expected, since an <input type="file"> is not sending data unless file is uploaded).
Just remove orphanRemoval=true and handle your logic of removal with less magic.

Please note that this behavior is not related to VichUploaderBundle, that's the way Doctrine is working.

I think removing orphanRemoval is not an option, because:

  • It's how ORM supposed to work.
  • Even removing orphanRemoval how we would know that user removed a file but not left unchanged?(Adding a delete checkbox? It's ugly solution in many cases. )

The really strange thing that it is used to work before. It looks like it's more related to Symfony than to Doctrine, since collection of attachments is empty.
A better way to add hidden field as I mention before or even add hidden field to VichType.

We can leave it as is, but I think this should be described in documentation since it's really break BC.

Of course, you can provide any additional field and solve the question. Your problem is exactly that the VichFileType alone is not enough to let the main entity know about its children are still there. But, as already mentioned, it would be exactly the same with a normal FileType, so there's nothing VichUploaderBundle can do to avoid it.

I know and I totally agree.
But it seems Symfony used to treat differently null and empty file type. It used to work before 3.3.
I just installed 3.2 and Vich 1.4 to check that again. And the result is that collection is not empty!
That means bundle breaks compatibility since 3.3 and should be fixed or covered in documentation.

I lost you on "that means bundle breaks compatibility".
How can you say that? Can you point to a change in this bundle that broke BC? If not, BC was broken elsewhere and can't be documented here.

I did not mean BC which is "Backward compatibility". I wrote " breaks compatibility" == " not compatible " that means that behavior is not the same as it used to before on symfony prior 3.3.

But such behavior is not related to this bundle. We already discussed about possible solutions, and all of them are outside this bundle

Thanks you @skornev for your hack with the file name field, it works for me.

garak, I think it's related because this bundle depends on symfony.

All I am trying to say is that currently composer file says that is compatible with 3.3 but strictly speaking it is not, because behavior differs on 3.3 and 3.2 and there is no any mention about that.

Close then?

And there will never be a mention, since it's not our fault.
I can't see any option other than closing this issue

I did not no say it was problem on vich bundle side, but if something changed in Symfony and bundle is not compatible with a new version anymore, shouldn't it be marked as not compatible with that version?

It's not about compatibility. A specific case is not working like before, and it's not even a case limited to this bundle (e.g. you're getting the same difference using your custom file upload solution).

It's an objective fact. Maybe you're right but this bundle is not compatible with Symfony 3.3, in specific case.
Or you can add this use case in documentation ?

You can propose to add such case to Symfony documentation, where it should belong

garak, I dont' agree until this specific cases not listed as "this usage of bundle is not guarantee from one symfony version to another"

Yes. Definitely it should be also mentioned in Symfony documentation.

The only changes we can document here are the ones related to this bundle.
We cannot cover changes made elsewhere.
If this bundle is not working for you with specific versions of Symfony (or Doctrine, or any other library), feel free to use different versions of Symfony (or Doctrine, etc.)

The issue is still actual for Symfony 4 in 2018. Files disappear when you save with orphanRemoval=true, with orphanRemoval=false your database is filled with orphaned file entries.

@danaki and all the considerations made above are still valid, unless you can bring some details we missed before. In such case, I'll be glad to re-open this issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

webkmua picture webkmua  路  4Comments

WassabiVl picture WassabiVl  路  3Comments

Marcelo-Petrucelli picture Marcelo-Petrucelli  路  3Comments

manguecreative picture manguecreative  路  4Comments

archie18 picture archie18  路  6Comments