I've been trying to use VichUploader to upload files on a Symfony project, already using EasyAdmin 3.
I've configured everything correctly, but I'm getting this error:
The "pieceJointeFile" image field must define the directory where the images are uploaded using the setUploadDir() method.
<?php
namespace App\Entity;
use App\Repository\InventaireRepository;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
My entity
/**
* @ORM\Entity(repositoryClass=InventaireRepository::class)
* @Vich\Uploadable
*/
class Inventaire
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity=Conducteur::class, inversedBy="inventaires")
*/
private $conducteur;
/**
* @ORM\Column(type="date")
*/
private $dateInventaire;
/**
* @ORM\Column(type="string", length=255)
*/
private $pieceJointe;
/**
* @Vich\UploadableField(mapping="pieceJointe", fileNameProperty="pieceJointe")
*/
private $pieceJointeFile;
/**
* @ORM\Column(type="datetime")
*/
private $updatedAt;
public function __construct()
{
$this->updatedAt = new DateTime();
}
public function getId(): ?int
{
return $this->id;
}
public function getConducteur(): ?Conducteur
{
return $this->conducteur;
}
public function setConducteur(?Conducteur $conducteur): self
{
$this->conducteur = $conducteur;
return $this;
}
public function getDateInventaire(): ?\DateTimeInterface
{
return $this->dateInventaire;
}
public function setDateInventaire(\DateTimeInterface $dateInventaire): self
{
$this->dateInventaire = $dateInventaire;
return $this;
}
public function getPieceJointeFile() {
return $this->pieceJointeFile;
}
public function setPieceJointeFile($pieceJointeFile): void
{
$this->pieceJointeFile = $pieceJointeFile;
if($pieceJointeFile) {
$this->updatedAt = new DateTime();
}
}
public function getPieceJointe() {
return $this->pieceJointe;
}
public function setPieceJointe($pieceJointe):self
{
$this->pieceJointe = $pieceJointe;
return $this;
}
public function getUpdatedAt()
{
return $this->updatedAt;
}
}
vich uploader configuration
vich_uploader:
db_driver: orm
mappings:
pieceJointe:
uri_prefix: /files/pieceJointe
upload_destination: '%kernel.project_dir%/public/files/pieceJointe'
and finally My crud controller
<?php
namespace App\Controller\Admin;
use App\Entity\Inventaire;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ImageField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Vich\UploaderBundle\Form\Type\VichFileType;
use Vich\UploaderBundle\Form\Type\VichImageType;
class InventaireCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Inventaire::class;
}
public function configureFields(string $pageName): iterable
{
return [
DateField::new('dateInventaire'),
AssociationField::new('conducteur'),
TextField::new('pieceJointeFile')->setFormType(VichFileType::class, [
'delete_label' => 'supprimer?'
])->onlyOnForms(),
ImageField::new('pieceJointe')->setBasePath('/files/pieceJointe')->onlyOnDetail(),
ImageField::new('pieceJointeFile')->setFormType(VichImageType::class)
];
}
public function configureActions(Actions $actions): Actions
{
return $actions
->add(Crud::PAGE_INDEX, Action::DETAIL);
}
}
Finally, I want to clarify that when using TextField
it works correctly.
Although EasyAdmin doesn't provide any built-in feature to upload files, it integrates seamlessly with VichUploaderBundle, the most popular file uploader Symfony bundle. Add the minimal configuration that makes the bundle work: First you'll learn how to upload and preview images in the backend.
Even if your application uses Symfony 3 there is no need to use the FQCN of the VichFileType ( type: 'Vich \UploaderBundle \Form \Type \VichFileType' ) because EasyAdmin supports the short types for some popular third-party bundles. EasyAdmin renders the VichUploaderBundle form fields using a custom form theme that improves their default styling.
If you prefer to use the original VichUploaderBundle styles, add its form theme in the form_theme configuration option (put it at the end to override EasyAdmin's default form theme): Apply the same technique in case you want to use your own form theme instead of the one provided by VichUploaderBundle.
VichUploader only supports to upload single files, so the only solution is to have a bridge entity with a OneToMany relation with the entity that contains the file, like you can see in this answer A viable alternative would be to create many different Image entities instead of trying to put multiple attachments to the same Image.
$imageFile = TextareaField::new('imageFile')->setFormType(VichImageType::class);
Put TextareaField to remplace the ImageField and it's works for me!!!!!
$imageFile = TextareaField
$image = ImageField
You can solve this problem by creating a simple field class
<?PHP
namespace App\Field;
use App\Form\MetaDataType;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
use Vich\UploaderBundle\Form\Type\VichImageType;
final class VichImageField implements FieldInterface
{
use FieldTrait;
public static function new(string $propertyName, ?string $label = 'Image'): self
{
return (new self())
->setProperty($propertyName)
->setLabel($label)
// this template is used in 'index' and 'detail' pages
->setTemplatePath('admin/field/vich_image.html.twig')
// this is used in 'edit' and 'new' pages to edit the field contents
// you can use your own form types too
->setFormType(VichImageType::class)
->addCssClass('field-vich-image')
;
}
}
And then use it in your crud controllers
use App\Field\VichImageField;
...
yield VichImageField::new('image')->hideOnForm();
yield VichImageField::new('imageFile')->onlyOnForms();
Two times here because you need image
field to render and imageFile
on forms
{# admin/field/vich_image.html.twig #}
{% if field.value %}
{% if field.value|match('/\.svg$/') %}
<div class="thumbnail">
{{ vich_uploader_asset(entity.instance, field.property ~ 'File', entity.fqcn) }}
</div>
{% else %}
{% set html_id = 'ea-lightbox-' ~ field.uniqueId %}
<a href="#" class="ea-lightbox-thumbnail" data-featherlight="#{{ html_id }}" data-featherlight-close-on-click="anywhere">
<img src="{{ vich_uploader_asset(entity.instance, field.property ~ 'File', entity.fqcn)|imagine_filter('admin_thumbnail') }}" alt="{{ entity.name }}" class="img-fluid">
</a>
<div id="{{ html_id }}" class="ea-lightbox">
<img src="{{ vich_uploader_asset(entity.instance, field.property ~ 'File', entity.fqcn)|imagine_filter('admin_full') }}" alt="{{ entity.name }}">
</div>
{% endif %}
{% else %}
<span class="badge badge-secondary">
Empty
</span>
{% endif %}
I found that documentation for EasyAdmin and VichUploaderBundle contains a mistake which follow to next exception: The "imageFile" image field must define the directory where the images are uploaded using the setUploadDir() method.
solution is simple:
//Entity
/**
*
* @Vich\UploadableField(mapping="video_image", fileNameProperty="imageName")
*
* @var File|null
*/
private $imageFile;
//......
/**
* @param File|null $imageFile
* @return $this
*/
public function setImageFile(File $imageFile = null): self
{
$this->imageFile = $imageFile;
if (null !== $imageFile) {
$this->updatedAt = new DateTime();
}
return $this;
}
//Admin Crud controller
// any type of field isnt correct except one
$coverImage = ImageField::new('imageFile')->setFormType(VichImageType::class);
//this is a proper way of how to
$coverImage = Field::new('imageFile')->setFormType(VichImageType::class);
not required to create any custom field type or anything else except proper configuration in vich_uploader.yaml
I have the same issue. I solved it by reverting to the version "easycorp/easyadmin-bundle": "3.1.6"
Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With