Known issues
September 9, 2026 ยท View on GitHub
The file is not updated if there are no other changes in the entity
As the bundle is listening to Doctrine prePersist and preUpdate events, which are not fired
when there is no change on field mapped by Doctrine, the file upload is not handled if the image field
is the only updated.
A workaround to solve this issue is to manually generate a change:
<?php
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class Product
{
// ...
#[ORM\Column(type: "datetime")]
private ?\DateTimeInterface $updatedAt = null;
// ...
public function setImageFile(?File $imageFile = null): void
{
$this->imageFile = $imageFile;
// Only change the updatedAt property if the file is really uploaded to avoid database updates.
// This is needed when the file should be set when loading the entity.
if ($this->imageFile instanceof UploadedFile) {
$this->updatedAt = new \DateTime('now');
}
}
}
See issue GH-123
Uploading files does not trigger Gedmo/DoctrineExtensions events
Similar to the issue above, because VichUploaderBundle relies on Doctrine's prePersist and
preUpdate events which occur after Gedmo's use of the preFlush event to execute it's own
handlers, it is not possible to use Gedmo's handlers to track changes for uploaded files. To be
more specific, you cannot use Gedmo\Timestampable to track when a file is uploaded or changed.
One solution for this is to update your timestamp property in your setters of the file and field
properties; updating both is necessary to track delete and change actions.
#[Vich\UploadableField(mapping: 'custom_file', fileNameProperty: 'myField')]
protected ?File $myFile = null;
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
protected ?string $myField = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
public private(set) ?\DateTime $myFieldUpdatedAt = null;
public function setMyFile(?File $file = null): void
{
$this->myFieldUpdatedAt = new \DateTime();
$this->myFile = $file;
}
public function setMyField(?string $myField = null): void
{
$this->myFieldUpdatedAt = new \DateTime();
$this->myField = $myField;
}
Image not deleted with cascade deletion and Doctrine
Just check the following options: cascade={"remove"} and orphanRemoval=true.
Vendor\Bundle\CoolBundle\Entity\CoolEntity:
type: entity
fields: ...
oneToMany:
images:
targetEntity: CoolEntityImage
mappedBy: bike
cascade: [persist, merge, remove]
orphanRemoval: true
No Upload is triggered when manually injecting an instance of Symfony\Component\HttpFoundation\File\File
An upload will only be triggered if an instance of Symfony\Component\HttpFoundation\File\UploadedFile
is injected into the setter for the Vich\UploadableField property of your class. Normally this is done
automatically if using Symfony Form but if your application logic is attempting to do this manually, and you
inject an instance of Symfony\Component\HttpFoundation\File\File instead the bundle will silently ignore
your attempted upload.
Consider the following class:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Attribute as Vich;
#[ORM\Entity]
#[Vich\Uploadable]
class Product
{
#[Vich\UploadableField(mapping: "products", fileNameProperty: "imageName")]
private ?File $imageFile = null;
/**
* 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|null $imageFile
*/
public function setImageFile(?File $imageFile = null): void
{
$this->imageFile = $imageFile;
}
}
If the bundle's configuration parameter inject_on_load is set to true the Product::setImageFile()
method above must take an instance of File as when this class is hydrated by Doctrine this
bundle will automatically inject an instance of File there. However, if you were to change
the image path to a new image in that instance of File and attempted a flush() nothing
would happen, instead inject a new instance of UploadedFile with the new path to your new
image to successfully trigger the upload.
N.B. : UploadedFile objects have a test mode that can be used to simulate file uploads. If you are going to insert images programmatically, make sure to set it to true, i.e.
<?php
$uploadedFile = new \Symfony\Component\HttpFoundation\File\UploadedFile($filePath, basename($filePath), null, null, true);
$entity->setFile( $uploadedFile );
Be aware that these files will be moved to the designated location by VichUploader, so if you want to keep the
original files intact, copy them to a temporary location first. If you plan to upload the same file multiple times,
you will need multiple different locations, otherwise the handler on the first VichUploader field will move the file
and accessing that file will fail on subsequent tries.
Note: The UploadedFile constructor changed in 4.1, if you're using a prior version, you will need to add a parameter
for the file size.
Failed to set metadata before uploading the file
When using Gaufrette with some specific adapters, it's possible that metadata can't be set when uploading a file. For some adapters, metadata need to be defined after the upload because setting the metadata for a given file results in a separate API call. In the other hand, for other adapters setting the metadata does not result in an API call: the metadata is joined with the file during the upload. To summarize, Gaufrette support for metadata is flawed (see issue GH-163).