Symfony 4 modifier l'image de profil de l'utilisateur

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Symfony 4 modifier l'image de profil de l'utilisateur

Re: Symfony 4 modifier l'image de profil de l'utilisateur

par Sandy » 11 juin 2019, 19:34

Merci pour ta réactivité !
J'essaye d'adapter sa technique à mon projet mais je comprend pas tout ! Surtout la déclaration des variables $originalFilename et $newFilename. Il utilise Gedmo apparemment, je crois que c'est un bundle pour creer des slugs...
if ($form->isSubmitted() && $form->isValid()) {
            /** @var UploadedFile $uploadedFile */
            $uploadedFile = $form['pictureFile']->getData();
            if ($uploadedFile) {
                $destination = $this->getParameter('kernel.project_dir') . '/public/uploads/pictures';
                $originalFilename = pathinfo($uploadedFile->getClientOriginalName(), PATHINFO_FILENAME);
                $newFilename = Urlizer::urlize($originalFilename) . '-' . uniqid() . '.' . $uploadedFile->guessExtension();
                $uploadedFile->move(
                    $destination,
                    $newFilename
                );
                $user->setPicture($newFilename);
            }
De mon côté, j'utilise Cocur sluggify, saurais-tu par quoi puis je remplacer cette fonction urlize ?

Re: Symfony 4 modifier l'image de profil de l'utilisateur

par Saian » 11 juin 2019, 16:00

Salut, j'ai l'impression que l'explication sur ce site à l'air pas mal https://symfonycasts.com/screencast/sym ... ad-in-form
J'ai survolé rapidement mais si j'ai bien compris, la clé semble être de déclarer le champ en mapped false dans le form type et c'est dans le controller que tu vas t'occuper de renseigner le chemin du fichier dans l'entité. Ainsi symfony ne va pas essayer de pousser un string dans le FileType puisqu'il ne sera plus lié à l'entité.

Symfony 4 modifier l'image de profil de l'utilisateur

par Sandy » 11 juin 2019, 15:21

Bonjour à tous !
Je recherche depuis plusieurs jours une solution pour éditer l'image de profil en vain ...
Voici ma classe User
<?php

namespace App\Entity;

use Cocur\Slugify\Slugify;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\PreUpdate;
use Doctrine\ORM\Mapping\PrePersist;
use Symfony\Component\Validator\Constraints\EqualTo;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;


/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @ORM\HasLifecycleCallbacks()
 * @UniqueEntity(
 * fields={"email"},
 * message={"cet email est déjà utilisé"}
 * )
 */
class User implements UserInterface, \Serializable
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     * @Assert\NotBlank()
     */
    private $pseudo;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     * @Assert\NotBlank()
     */
    private $lastname;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     * @Assert\NotBlank()
     */
    private $firstname;

    /**
     * @ORM\Column(type="string")
     * @Assert\NotBlank(message="Veuillez charger une image")
     * @Assert\File(mimeTypes={ "image/jpeg" })
     */
    private $picture;

    /**
     * @ORM\Column(type="string", length=1, nullable=true)
     */
    private $sex;

    /**
     * @ORM\Column(type="date", nullable=true)
     * @Assert\NotBlank()
     */
    private $birth;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     * @Assert\NotBlank()
     */
    private $address;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $phone;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $slug;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     * @Assert\Email(message="Renseignez un email valide")
     */
    private $email;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $hash;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     * @Assert\Url(message="Renseignez une Url valide")
     */
    private $paypal;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     * @Assert\Url(message="Renseignez une Url valide")
     */
    private $amazon;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     * @Assert\Url(message="Renseignez une Url valide")
     */
    private $ebay;

    /**
     * @Assert\EqualTo(propertyPath="hash", message="Le mot de passe doit être identique")
     */
    public $passwordConfirm;

    /**
     * Initialiser le slug
     * 
     * @ORM\PrePersist
     * @ORM\PreUpdate
     * 
     * @return void
     */
    public function initializeSlug()
    {
        if (empty($this->slug)) {
            $slugify = new Slugify();
            $this->slug = $slugify->slugify($this->lastname . '' . $this->firstname);
        }
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getPseudo(): ?string
    {
        return $this->pseudo;
    }

    public function setPseudo(?string $pseudo): self
    {
        $this->pseudo = $pseudo;

        return $this;
    }

    public function getLastname(): ?string
    {
        return $this->lastname;
    }

    public function setLastname(?string $lastname): self
    {
        $this->lastname = $lastname;

        return $this;
    }

    public function getFirstname(): ?string
    {
        return $this->firstname;
    }

    public function setFirstname(?string $firstname): self
    {
        $this->firstname = $firstname;

        return $this;
    }

    public function getPicture(): ?string
    {
        return $this->picture;
    }

    public function setPicture(?string $picture): self
    {
        $this->picture = $picture;

        return $this;
    }

    public function getSex(): ?string
    {
        return $this->sex;
    }

    public function setSex(?string $sex): self
    {
        $this->sex = $sex;

        return $this;
    }

    public function getBirth(): ?\DateTimeInterface
    {
        return $this->birth;
    }

    public function setBirth(?\DateTimeInterface $birth): self
    {
        $this->birth = $birth;

        return $this;
    }

    public function getAddress(): ?string
    {
        return $this->address;
    }

    public function setAddress(?string $address): self
    {
        $this->address = $address;

        return $this;
    }

    public function getPhone(): ?string
    {
        return $this->phone;
    }

    public function setPhone(?string $phone): self
    {
        $this->phone = $phone;

        return $this;
    }

    public function getSlug(): ?string
    {
        return $this->slug;
    }

    public function setSlug(?string $slug): self
    {
        $this->slug = $slug;

        return $this;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(?string $email): self
    {
        $this->email = $email;

        return $this;
    }

    public function getHash(): ?string
    {
        return $this->hash;
    }

    public function setHash(string $hash): self
    {
        $this->hash = $hash;

        return $this;
    }

    public function getPaypal(): ?string
    {
        return $this->paypal;
    }

    public function setPaypal(?string $paypal): self
    {
        $this->paypal = $paypal;

        return $this;
    }

    public function getAmazon(): ?string
    {
        return $this->amazon;
    }

    public function setAmazon(?string $amazon): self
    {
        $this->amazon = $amazon;

        return $this;
    }

    public function getEbay(): ?string
    {
        return $this->ebay;
    }

    public function setEbay(?string $ebay): self
    {
        $this->ebay = $ebay;

        return $this;
    }

    public function getRoles()
    {
        return ['ROLE_USER'];
    }

    public function getPassword()
    {
        return $this->hash;
    }

    public function getSalt()
    { }

    public function getUsername()
    {
        return $this->email;
    }

    public function eraseCredentials()
    { }

    /** @see \Serializable::serialize() */
    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->pseudo,
            $this->lastname,
            $this->firstname,
            $this->picture,
            $this->sex,
            $this->birth,
            $this->address,
            $this->phone,
            $this->slug,
            $this->email,
            $this->hash,
            $this->paypal,
            $this->amazon,
            $this->ebay,
            // see section on salt below
            // $this->salt,
        ));
    }

    /** @see \Serializable::unserialize() */
    public function unserialize($serialized)
    {
        list(
            $this->id,
            $this->pseudo,
            $this->lastname,
            $this->firstname,
            $this->picture,
            $this->sex,
            $this->birth,
            $this->address,
            $this->phone,
            $this->slug,
            $this->email,
            $this->hash,
            $this->paypal,
            $this->amazon,
            $this->ebay,
            // see section on salt below
            // $this->salt
        ) = unserialize($serialized);
    }

    public function getFullName()
    {
        return "{$this->getFirstname()} {$this->getLastname()}";
    }
}
Voici les 2 méthodes du AccountController qui permettent l'inscription du user et la modification du profil
/**
     * Permet d'afficher le formulaire d'inscription
     * @Route("/register", name="account_register")
     * @return Response
     */
    public function register(Request $request, ObjectManager $manager, UserPasswordEncoderInterface $encoder)
    {
        $user = new User();
        $form = $this->createForm(RegistrationType::class, $user);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            //encoder les mots de passe
            $hash = $encoder->encodePassword($user, $user->getHash());
            $user->setHash($hash);

            //upload des images
            $file = $form->get('picture')->getData();
            $fileName = $this->generateUniqueFileName() . '.' . $file->guessExtension();
            $fileName = $user->getFileName();
            //Déplace le fichier dans le dossier upload
            try {
                $file->move(
                    $this->getParameter('upload_directory'),
                    $fileName
                );
            } catch (FileException $e) { }

            $user->setPicture($fileName);

            $manager->persist($user);
            $manager->flush();

            $this->addFlash(
                'success',
                "Votre compte a bien été créé"
            );

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

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

    /**
     * @return string
     */
    private function generateUniqueFileName()
    {
        // md5() reduces the similarity of the file names generated by
        // uniqid(), which is based on timestamps
        return md5(uniqid());
    }

    /**
     * Permet d'afficher le formulaire d'édition du profil
     * @Route("/account/profile", name="account_profile")
     * 
     * @return Response
     */
    public function profile(Request $request, ObjectManager $manager)
    {
        $user = $this->getUser();
        $picture = $user->getPicture();
        if (!is_null($picture)) {
            $user->setPicture($picture);
        }

        $form = $this->createForm(AccountType::class, $user);
        $form->handleRequest($request);


        if ($form->isSubmitted() && $form->isValid()) {
            // $file stores the uploaded jpeg file
            /** @var Symfony\Component\HttpFoundation\File\UploadedFile $file */
            $file = $form->get('picture')->getData();
            if ($file !== null) {
                $user->setPicture(
                    new File($this->getParameter('upload_directory') . '/' . $user->getPicture())
                );
                $fileName = $this->generateUniqueFileName() . '.' . $file->guessExtension();
                $fileName = $user->getFileName();
                //Déplace le fichier dans le dossier upload
                try {
                    $file->move(
                        $this->getParameter('upload_directory'),
                        $fileName
                    );
                } catch (FileException $e) { }

                $user->setPicture($fileName);
            } else {
                $user->setPicture($picture);
            }

            $manager->persist($user);
            $manager->flush();

            $this->addFlash(
                'success',
                "Les modifications ont bien été enregistrées"
            );

            return $this->redirect($this->generateUrl('user_show'));
            //return $this->redirectToRoute('user_show', ['slug' => $user->getSlug()]);
        }

        return $this->render('account/profile.html.twig', [
            'form' => $form->createView()
        ]);
    }
Ici le fichier AccountType qui génére le formulaire d'édition du profil
class AccountType extends ApplicationType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('pseudo', TextType::class, $this->getConfiguration("Pseudo", "Votre pseudo..."))
            ->add('lastname', TextType::class, $this->getConfiguration("Nom", "Votre nom..."))
            ->add('firstname', TextType::class, $this->getConfiguration("Prénom", "Votre prénom..."))
            ->add('picture', FileType::class, $this->getConfiguration("Image de profil", ""), array(
                'data_class' => null,
                'required' => false
            ))
            ->add('sex', ChoiceType::class, array(
                'label' => "Sexe",
                'choices' => array(
                    'Feminin' => 1,
                    'Masculin' => 0,
                ),
                'expanded' => true,
                'multiple' => false
            ))
            ->add('birth', BirthdayType::class, $this->getConfiguration("Date de naissance", "Votre date de naissance..."))
            ->add('address', TextType::class, $this->getConfiguration("Adresse", "Votre adresse..."))
            ->add('phone', TextType::class, $this->getConfiguration("Téléphone", "Votre numéro de téléphone..."))
            ->add('email', EmailType::class, $this->getConfiguration("Email", "Votre email..."))
            ->add('paypal', UrlType::class, $this->getConfiguration("Compte Paypal", "Votre compte Paypal..."))
            ->add('amazon', UrlType::class, $this->getConfiguration("Compte Amazon", "Votre compte Amazon..."))
            ->add('ebay', UrlType::class, $this->getConfiguration("Compte Ebay", "Votre compte Ebay..."));
    }
A ce stade là, lorsque je veux accéder au formulaire d'édition du profil j'ai cette erreur :
The form's view data is expected to be an instance of class Symfony\Component\HttpFoundation\File\File, but is a(n) string. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) string to an instance of Symfony\Component\HttpFoundation\File\File.

Pour pallier à cela, j'avais ajouté une propriété non mappée à mon entité user, que je donnais à mon accountType mais du coup à la soumission du formulaire, j'avais le message "le fichier n'a pas été trouvé"

Quelle est la procédure pour modifier cette image? Je ne trouve pas de réponse à mon problème, merci par avance pour votre aide :)