Symfony + VichUploader

Par Amstramgram, il y a 4 ans


Hello,
je suis entrain de faire une API avec symfony 5.2.8. Et j'en suis à l'étape de l'upload des fichiers.
Pour tester ca, je voulais ajouter un avatar sur l'utilisateur.

Mais je ne comprend pas trop l'erreur que j'ai :

Mapping not found for field "avatarFile"

Voici le code que j'utilise :

/** * @ORM\Entity(repositoryClass=UserRepository::class) * @ORM\Table(name="`users`") * @ORM\HasLifecycleCallbacks * @Vich\Uploadable * * @OA\Schema */ class User implements UserInterface, JWTUserInterface { /** * @Vich\UploadableField(mapping="avatars", fileNameProperty="avatar") * @var File|null */ private ?File $avatarFile = null; /** * @ORM\Column(type="string", length=255, nullable=false) * * @Groups({"user:read"}) */ private string $avatar = ""; public function getAvatarFile(): ?File { return $this->avatarFile; } public function setAvatarFile(?File $file): self { $this->avatarFile = $file; if($this->avatarFile instanceof UploadedFile){ $this->updateTimestamps(); } return $this; } public function getAvatar(): ?string { return $this->avatar; } public function setAvatar(string $avatar): self { $this->avatar = $avatar; return $this; } } class UserForm extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('username', TextType::class) ->add('email', EmailType::class) ->add('password', PasswordType::class) ->add('avatarFile', VichFileType::class, [ 'required' => false, ]); } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class' => UserData::class, 'csrf_protection' => false ]); } } public function create(UserPasswordEncoderInterface $encoder): JsonResponse { $data = new UserData(); $data->encoder = $encoder; $data->entity = new User(); $data->avatarFile = $this->getCurrentRequest()->files->get('avatar'); return $this->crudCreate($data); } $form = $this->createForm($data->getFormClass(), $data); //$form->handleRequest($request); // ne fonctionne pas, remplacé par submit() $form->submit($request->request->all(), ($request->getMethod() != 'PATCH')); if( $form->isSubmitted() && $form->isValid() ){ $entity = $data->getEntity(); $data->hydrate(); $this->em->persist($entity); }

Si vous avez une piste,
Merci.

5 réponses

Amstramgram, il y a 4 ans

bon je ne sais pas trop pourquoi mais is je retire le

->add('avatarFile', VichFileType::class, [ 'required' => false, ]);

cela fonctionne.
Merci pour votre aide.

htachoires, il y a 4 ans

Hello Amstramgram, Vich s'attend à ce que tu crée une configuration dans le fichier config/packages/vich_uploader.yaml avec un truc qui ressemble à ça :

vich_uploader: db_driver: orm mappings: file_mapping: # Le nom du mapping uri_prefix: '%upload_path%' upload_destination: '%kernel.project_dir%/public/%upload_path%' namer: vich_uploader.namer_uniqid

Je t'invite à lire la doc du Bundle.

Amstramgram, il y a 4 ans

Hello, désolé j'ai oublié de mettre la config de mapping mais je l'ai bien dans config/packages/vich_uploader.yaml avec la mapping avatars que j'utilise dans l'entity.

vich_uploader: db_driver: orm mappings: avatars: uri_prefix: /uploads/avatars upload_destination: '%kernel.project_dir%/public/uploads/avatars' namer: service: Vich\UploaderBundle\Naming\PropertyNamer options: { property: 'id' } directory_namer: service: App\Utils\Uploader\PropertyUserDirectoryNamer inject_on_load: false delete_on_update: true delete_on_remove: true
Grafikart, il y a 4 ans

Vide le cache et ça ne fixe pas le pb essaie de faire une erreur dans le yaml pour voir si il est bien pris en compte.

Amstramgram, il y a 4 ans

J'ai vidé le cache même erreur.
Et si je fais une erreur dans le fichier yaml, j'ai une erreur avec le FileLoader.php, YamlFileLoader.php et Parser.php.

Et mon UserData

<?php namespace App\Component\User\Data; use App\Component\User\Entity\User; use App\Component\User\Form\UserForm; use App\Utils\Base\BaseCrudDataInterface; use App\Utils\Validator\Unique; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; use Symfony\Component\Validator\Constraints as Assert; use Vich\UploaderBundle\Mapping\Annotation as Vich; /** * @Unique(field="email") * @Unique(field="username") * @Vich\Uploadable */ class UserData implements BaseCrudDataInterface { private EntityManagerInterface $em; private bool $isUpdate = false; private array $required = ['username', 'email', 'password']; public User $entity; public UserPasswordEncoderInterface $encoder; /** * @Assert\NotBlank() * @Assert\Email() */ public string $email = ""; /** * @Assert\NotBlank() * @Assert\Type(type="alnum", message="This value should contain only letter or number.") */ public string $username = ""; /** * @Assert\NotBlank() * @Assert\Length(min=8, max=128) * @Assert\NotCompromisedPassword() */ public string $password = ""; /** * @Assert\NotBlank() * @Assert\Image(mimeTypes={"image/jpeg", "image/jpg", "image/png"}, minWidth=120, maxHeight=1400, maxWidth=1400, minHeight=120) */ public ?UploadedFile $avatarFile = null; //public string $avatar = ""; public static function clone(User $user): self { $data = new self(); $data->username = $user->getUsername(); $data->email = $user->getEmail(); $data->password = $user->getPassword(); $data->avatarFile = $user->getAvatarFile(); //$data->avatar = $user->getAvatar(); $data->entity = $user; $data->isUpdate = true; return $data; } public function hydrate(): void { $this->entity->setEmail($this->email); $this->entity->setUsername($this->username); $this->entity->setAvatarFile($this->avatarFile); $this->entity->setAvatar($this->avatar); if( !$this->isUpdate ){ $this->entity->setPassword($this->encoder->encodePassword($this->entity, $this->password)); } } public function getEntity(): User { return $this->entity; } public function getFormClass(): string { return UserForm::class; } public function setEntityManager(EntityManagerInterface $em): self { $this->em = $em; return $this; } public function getId(): string { return $this->getEntity()->getId(); } public function getRequiredFields(): array { return $this->required; } }