To combine the answers and address an issue with VichUploader and inject_on_load: true changing the updatedAt during the postLoad event.
Explanation of the issue
Since the VichUploader mapped property is not monitored by Doctrine ORM, you will need to ensure at least one of the properties that the ORM manages is changed to trigger the prePersist or preUpdate events that VichUploader uses to manage the file reference.
This is generally done by using an updatedAt DATETIME column in your file setter but can be any property that is managed by the ORM.
postLoad event setter File instance issue
Verifying an instance of UploadedFile is supplied to the mapped property setter method, will ensure that updatedAt is changed only during Form submissions or when manually supplied, instead of during the postLoad event - where VichUpload supplies an instance of File to the same mapped setter method. Which would otherwise cause the updatedAt value in your views to change and potentially change the database value if you call $em::flush() when instances of the Image object are loaded by Doctrine and therefor managed.
App\Entity\Image
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* @ORM\Entity
* @Vich\Uploadable
*/
class Image
{
/**
* @var \DateTime
* @ORM\Column(name="updated_at", type="datetime")
*/
private $updatedAt;
/**
* @var \Symfony\Component\HttpFoundation\File\File
* @Vich\UploadableField(mapping="your_mapping", fileNameProperty="image")
*/
private $imageFile;
/**
* @var string|null
* @ORM\Column(name="image", type="string", length=255, nullable=true)
*/
private $image;
public function __construct()
{
$this->updatedAt = new \DateTime('now');
}
//...
public function setImageFile(File $image = null)
{
$this->imageFile = $image;
if ($image instanceof UploadedFile) {
$this->updatedAt = new \DateTime('now');
}
}
}
Then you can manually define the file to use in your entity by instantiating an UploadedFile object and setting the error argument as null and the test argument to true, which disables validating UPLOAD_ERR_OK and is_uploaded_file() [sic].
Symfony <= 4.0
use Symfony\Component\HttpFoundation\File\UploadedFile;
$file = new UploadedFile($path, $filename, null, filesize($path), null, true);
Symfony 4.1+
In Symfony 4.1 and later, the file size argument was deprecated.
use Symfony\Component\HttpFoundation\File\UploadedFile;
$file = new UploadedFile($path, $filename, null, null, true);
Now you can successfully persist and/or flush your entity with the manually uploaded file.
$image = new Image();
$image->setImageFile($file);
$em->persist($image);
$em->flush();