cessother
cessother

Reputation: 127

On edit, FileType is empty even with setting newFile

FileType on edit stays empty even when setting new file at the beginning.

I've tried to put the value in the form, to set the name of the file before creating form, but still empty. I use Symfony4 and bootstrap 4.

public function edit(Request $request, ObjectManager $manager, SkillRepository $skillRepo, SkillWantRepository $skillWantRepo)
{
    $skilles = $skillRepo->findAll();
    $skillesWant = $skillWantRepo->findAll();
    //getUser appartient à Symfony, il récupère l'utilisateur connecté
    $user = $this->getUser();
    $skill = new Skill();
    $skillWant = new SkillWant();
    $fileName = $user->getAvatar();
    $user->setAvatar(
        new File($this->getParameter('avatars_directory') . '/' . $user->getAvatar())
    );  
    $form = $this->createForm(AccountType::class, $user);
    $test =$user->getAvatar();

    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $file = $form->get('avatar')->getData();
        /** @var Symfony\Component\HttpFoundation\File\UploadedFile $file*/
        $fileName = $this->generateUniqueFileName() . '.' . $file->guessExtension();
        try {
            $file->move(
                $this->getParameter('avatars_directory'),
                $fileName
            );
        } catch (FileException $e) {
            // ... handle exception if something happens during file upload
        }

        //on stocke le nom du fichier dans la db
        // instead of its contents
        $user->setAvatar($fileName);

The form

->add('description', TextareaType:: class, ['required' => false])
->add('avatar', FileType:: class ,['data_class'=>null,'required'=>false, 'label'=>'votre image de profil'])`

I'd like to get the file in my download field but I get This error : Expected argument of type "string", "NULL" given at property path "avatar

Upvotes: 1

Views: 514

Answers (1)

Brent Pfister
Brent Pfister

Reputation: 505

You are close. It is difficult because the 'avatar' property holds either a string filename or an UploadedFile. The property type is checked by the client browser, the form validator, and the database. Also https://symfony.com/doc/current/controller/upload_file.html has some omissions and does not have example Controller code for editing an entity. Try this.

  1. Add these annotations on the Entity property 'avatar' to be uploaded: (See https://symfony.com/doc/current/reference/constraints/Image.html)
/**
 * @ORM\Column(type="string", length=255, nullable=true)
 *
 * @Assert\Type(
 *    type="File",
 *    message="The value {{ value }} is not a valid {{ type }}.")
 * @Assert\Image()
 */
private $avatar;

If 'avatar' were holding a non-image file such as a PDF file, the annotations would be: (See https://symfony.com/doc/current/reference/constraints/File.html)

/**
 * @ORM\Column(type="string", length=255, nullable=true)
 *
 * @Assert\Type(
 *    type="File",
 *    message="The value {{ value }} is not a valid {{ type }}.")
 * @Assert\File(mimeTypes={ "application/pdf" })
 */
private $avatar;
  1. In the Entity file, remove the type hints that were added by php bin/console make:entity
public function getAvatar(): ?string
{
    return $this->avatar;
}

should be changed to:

public function getAvatar()
{
    return $this->avatar;
}

and

public function setAvatar(?string $avatar): self
{
    $this->avatar = $avatar;
    return $this;
}

should be changed to:

public function setAvatar($avatar): self
{
    $this->avatar = $avatar;
    return $this;
}
  1. The Controller new() function should look like this: (You need to change occurrences of User2 to your entity name)
public function new(Request $request): Response
{
    $user2 = new User2();
    $form = $this->createForm(User2Type::class, $user2);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        // $file stores the uploaded picture file.
        /** @var Symfony\Component\HttpFoundation\File\UploadedFile $file */
        $file = $user2->getAvatar();
        $filename = null;
        if ($file != null) {
            $filename = $this->generateUniqueFileName().'.'.$file->guessExtension();

            // Move the file to the directory where pictures are stored
            try {
                $file->move(
                    $this->getParameter('avatars_directory'),
                    $filename
                );
            } catch (FileException $e) {
                // ... handle exception if something happens during file upload
            }
        }

        // Updates the avatar property to store the picture file name
        // instead of its contents.
        $user2->setAvatar($filename);

        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($user2);
        $entityManager->flush();

        return $this->redirectToRoute('user2_index');
    }

    return $this->render('user2/new.html.twig', [
        'user2' => $user2,
        'form' => $form->createView(),
    ]);
}
  1. In the Controller edit() function, because an avatar is optional, the code needs to check for a null avatar.
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;

...

public function edit(Request $request, User2 $user2): Response
{
    $fileName = $user2->getAvatar();
    $oldFileName = $fileName;

    $form = $this->createForm(User2Type::class, $user2);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        /** @var Symfony\Component\HttpFoundation\File\UploadedFile $file*/
        $file = $form->get('avatar')->getData();
        if ($file != null) {
            // The user changed the avatar.
            $fileName = $this->generateUniqueFileName() . '.' . $file->guessExtension();
            try {
                $file->move(
                    $this->getParameter('avatars_directory'),
                    $fileName
                );
                // Delete the old file, if any.
                if ($oldFileName != null) {
                    try {
                        $filesystem = new Filesystem();
                        $filesystem->remove([$this->getParameter('avatars_directory') . '/' . $oldFileName]);
                    } catch (IOExceptionInterface $ioe) {
                        // ... handle exception if something happens during old file removal
                    }
                }
            } catch (FileException $e) {
                // ... handle exception if something happens during moving uploaded file to avatars directory.
                $fileName = $oldFileName;
            }
        }

        $user2->setAvatar($fileName);

        $this->getDoctrine()->getManager()->flush();

        return $this->redirectToRoute('user2_index', [
            'id' => $user2->getId(),
        ]);
    }

    return $this->render('user2/edit.html.twig', [
        'user2' => $user2,
        'form' => $form->createView(),
    ]);
}

Since you are using the Bootstrap theme, also see this question Symfony 4 Form file upload field does not show selected filename with Bootstrap 4 theme

Upvotes: 1

Related Questions