Solución:
La respuesta aceptada no es correcta (¿ya?). De acuerdo con la documentación de uso, puede cargar manualmente un File
sin usar el componente de formulario de Symfony:
/**
* 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|SymfonyComponentHttpFoundationFileUploadedFile $image
*/
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');
}
}
Deberías usar SymfonyComponentHttpFoundationFileUploadedFile
en lugar de File
:
$file = new UploadedFile($filename, $filename, null, filesize($filename), false, true);
VichUploaderBundle
manejará este objeto.
Para combinar las respuestas y abordar un problema con VichUploader y inject_on_load: true
cambiando el updatedAt
durante el postLoad
evento.
Explicación del problema
Dado que la propiedad mapeada de VichUploader no es monitoreada por Doctrine ORM, deberá asegurarse de que al menos una de las propiedades que administra el ORM se cambie para activar la prePersist
o preUpdate
eventos que VichUploader usa para administrar la referencia del archivo.
Esto generalmente se hace usando un updatedAt
Columna DATETIME en su configurador de archivos, pero puede ser cualquier propiedad administrada por el ORM.
postLoad
organizador de eventos File
problema de instancia
Verificando una instancia de UploadedFile
se suministra al método de establecimiento de propiedades mapeado, se asegurará de que updatedAt
está cambiado solamente durante los envíos de formularios o cuando se suministran manualmente, en lugar de durante el postLoad
evento – donde VichUpload proporciona una instancia de File
al mismo método de establecedor mapeado. Lo que de otra manera causaría updatedAt
valor en sus vistas para cambiar y potencialmente cambiar el valor de la base de datos si llama $em::flush()
cuando instancias de la Image
Los objetos son cargados por Doctrine y, por lo tanto, administrados.
Aplicación Entidad Imagen
namespace AppEntity;
use DoctrineORMMapping as ORM;
use SymfonyComponentHttpFoundationFileFile;
use SymfonyComponentHttpFoundationFileUploadedFile;
use VichUploaderBundleMappingAnnotation as Vich;
/**
* @ORMEntity
* @VichUploadable
*/
class Image
{
/**
* @var DateTime
* @ORMColumn(name="updated_at", type="datetime")
*/
private $updatedAt;
/**
* @var SymfonyComponentHttpFoundationFileFile
* @VichUploadableField(mapping="your_mapping", fileNameProperty="image")
*/
private $imageFile;
/**
* @var string|null
* @ORMColumn(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');
}
}
}
Luego, puede definir manualmente el archivo para usar en su entidad creando una instancia UploadedFile
objeto y configuración de la error
argumento como null
y el test
argumento para true
, que inhabilita la validación UPLOAD_ERR_OK
y is_uploaded_file()
[sic].
Symfony <= 4.0
use SymfonyComponentHttpFoundationFileUploadedFile;
$file = new UploadedFile($path, $filename, null, filesize($path), null, true);
Symfony 4.1 o superior
En Symfony 4.1 y posteriores, el argumento del tamaño del archivo quedó obsoleto.
use SymfonyComponentHttpFoundationFileUploadedFile;
$file = new UploadedFile($path, $filename, null, null, true);
Ahora puede conservar y / o vaciar con éxito su entidad con el archivo cargado manualmente.
$image = new Image();
$image->setImageFile($file);
$em->persist($image);
$em->flush();