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
Auteur
Réponse acceptée

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

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

cela fonctionne.
Merci pour votre aide.

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.

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

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.

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;
    }
}