Upload Fichier VichUploaderBundle

Ce sujet est résolu
Default
,

Bonjour,

J’utilise le Bundle VichUploaderBundle pour les envois de fichier.
Mais je rencontre un message d'erreur lors d'envois de fichier.

message d’erreur :

  • "Serialization of 'Symfony\Component\HttpFoundation\File\File' is not allowed"

Je ne vois pas où est mon erreur, j'ai suivis à la lettre la documentation :

Pour info, mon fichier est quand même bien envoyer malgré tout.

12 Réponse

87112
,

Ton entité User est effectivement sérialisée dans le composant sécurité. Et le message est clair, un élément de Type File n'est pas sérialisable...
Tu peux définir manuellemenent comment est sérialisé ton User (tu implémentes \Serializable et tu définis les fonctions serialize et unserialize).
Perso, je préfère laisser mon entité User avec les données minimales d'authentification, et créer une entité Profile liée en OneToOne, qui elle ne sera pas sérialisée.
Après c'est un choix à faire.

87112
,

Hello,

Effectivement, j'avais implémenté l'interface serializable dans mon entité Profile, autant pour moi. Ajoutes dans ton entity Profile:

// Profile implements Serializable Interface
class Profile implements \Serializable {
.... 
 /**
     * String representation of object
     * @link https://php.net/manual/en/serializable.serialize.php
     * @return string the string representation of the object or null
     * @since 5.1.0
     */
    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->imageName,
        ));
    }

    /**
     * Constructs the object
     * @link https://php.net/manual/en/serializable.unserialize.php
     * @param string $serialized <p>
     * The string representation of the object.
     * </p>
     * @return void
     * @since 5.1.0
     */
    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->imageName,
            ) = unserialize($serialized, array('allowed_classes' => false));
    }
}
87112
,

Hello,

Il nous faudrait plus de matière pour t'aider :

  • le code de ton entity (es-ce une entité User qui est serialisée par le composant sécurité de Symfony?)
  • le code de ton controlller
  • ...
Default
,

Voici le code de mon entity ( en l'occurrence User)

<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Mapping\Annotation as Vich;


/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @UniqueEntity(fields={"username"}, message="Il existe déjà un compte avec ce nom d'utilisateur")
 * @UniqueEntity(fields={"email"}, message="Il existe déjà un compte avec cet Email")
 * @Vich\Uploadable()
 */
class User implements UserInterface
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true, )
     * @Assert\Length(min="3", minMessage="Minimum 3 caractères")
     */
    private $username;

    /**
     * @ORM\Column(type="json")
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     */
    private $password;

    /**
     * @var string The hashed password
     * @Assert\EqualTo(propertyPath="password", message="Cette valeur doit être égale au 1er mot de passe")
     */
    private $confirm_password;

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

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

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

    /**
     * @ORM\Column(type="datetime")
     */
    private $createdAt;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="user")
     */
    private $comments;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Post", mappedBy="user")
     */
    private $posts;

    /**
     * @ORM\Column(type="boolean")
     */
    private $verified;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Category", mappedBy="user")
     */
    private $categories;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Security", mappedBy="user")
     */
    private $securities;

    /**
     * @ORM\Column(type="datetime")
     */
    private $modifiedAt;

    /**
     * NOTE: This is not a mapped field of entity metadata, just a simple property.
     * @Vich\UploadableField(mapping="avatars_images", fileNameProperty="imageName")
     * @var File
     */
    private $imageFile;

    /**
     * @ORM\Column(type="string", length=255)
     * @var string|null
     */
    private $imageName;

    /**
     * User constructor.
     */
    public function __construct()
    {
        $this->createdAt = new \DateTime('now');
        $this->modifiedAt = new \DateTime('now');
        $this->roles = ['ROLE_USER'];
        $this->comments = new ArrayCollection();
        $this->posts = new ArrayCollection();
        $this->categories = new ArrayCollection();
        $this->verified = 0;
        $this->securities = new ArrayCollection();
        $this->imageName = 'empty.png';
    }

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

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUsername(): string
    {
        return (string)$this->username;
    }

    public function setUsername(string $username): self
    {
        $this->username = $username;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): self
    {
        $this->roles = $roles;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getPassword(): string
    {
        return (string)$this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getSalt()
    {
        // not needed when using the "bcrypt" algorithm in security.yaml
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary, sensitive data on the user, clear it here
        // $this->plainPassword = null;
    }

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

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

        return $this;
    }

    public function getFirstName(): ?string
    {
        return $this->firstName;
    }

    public function setFirstName(?string $firstName): self
    {
        $this->firstName = $firstName;

        return $this;
    }

    public function getLastName(): ?string
    {
        return $this->lastName;
    }

    public function setLastName(?string $lastName): self
    {
        $this->lastName = $lastName;

        return $this;
    }

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

    public function setCreatedAt(\DateTimeInterface $createdAt): self
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getConfirmPassword()
    {
        return $this->confirm_password;
    }

    /**
     * @param mixed $confirm_password
     */
    public function setConfirmPassword($confirm_password): void
    {
        $this->confirm_password = $confirm_password;
    }

    /**
     * @return Collection|Comment[]
     */
    public function getComments(): Collection
    {
        return $this->comments;
    }

    public function addComment(Comment $comment): self
    {
        if (!$this->comments->contains($comment)) {
            $this->comments[] = $comment;
            $comment->setUser($this);
        }

        return $this;
    }

    public function removeComment(Comment $comment): self
    {
        if ($this->comments->contains($comment)) {
            $this->comments->removeElement($comment);
            // set the owning side to null (unless already changed)
            if ($comment->getUser() === $this) {
                $comment->setUser(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|Post[]
     */
    public function getPosts(): Collection
    {
        return $this->posts;
    }

    public function addPost(Post $post): self
    {
        if (!$this->posts->contains($post)) {
            $this->posts[] = $post;
            $post->setUser($this);
        }

        return $this;
    }

    public function removePost(Post $post): self
    {
        if ($this->posts->contains($post)) {
            $this->posts->removeElement($post);
            // set the owning side to null (unless already changed)
            if ($post->getUser() === $this) {
                $post->setUser(null);
            }
        }

        return $this;
    }

    public function getVerified(): ?bool
    {
        return $this->verified;
    }

    public function setVerified(bool $verified): self
    {
        $this->verified = $verified;

        return $this;
    }

    /**
     * @return Collection|Category[]
     */
    public function getCategories(): Collection
    {
        return $this->categories;
    }

    public function addCategory(Category $category): self
    {
        if (!$this->categories->contains($category)) {
            $this->categories[] = $category;
            $category->setUser($this);
        }

        return $this;
    }

    public function removeCategory(Category $category): self
    {
        if ($this->categories->contains($category)) {
            $this->categories->removeElement($category);
            // set the owning side to null (unless already changed)
            if ($category->getUser() === $this) {
                $category->setUser(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|Security[]
     */
    public function getSecurities(): Collection
    {
        return $this->securities;
    }

    public function addSecurity(Security $security): self
    {
        if (!$this->securities->contains($security)) {
            $this->securities[] = $security;
            $security->setUser($this);
        }

        return $this;
    }

    public function removeSecurity(Security $security): self
    {
        if ($this->securities->contains($security)) {
            $this->securities->removeElement($security);
            // set the owning side to null (unless already changed)
            if ($security->getUser() === $this) {
                $security->setUser(null);
            }
        }

        return $this;
    }

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

    public function setModifiedAt(): self
    {
        $this->modifiedAt = new \DateTime('now');

        return $this;
    }

    /**
     * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
     * of 'UploadedFile' is injected into this setter to trigger the update. If this
     * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
     * must be able to accept an instance of 'File' as the bundle will inject one here
     * during Doctrine hydration.
     *
     * @param File|UploadedFile $imageFile
     * @return User
     * @throws \Exception
     */
    public function setImageFile(?File $imageFile = null): User
    {
        $this->imageFile = $imageFile;
        if ($this->imageFile instanceof UploadedFile) {
            $this->modifiedAt = new \DateTime('now');
        }
        return $this;
    }

    public function getImageFile(): ?File
    {
        return $this->imageFile;
    }

    public function setImageName(?string $imageName): void
    {

        $this->imageName = $imageName;
    }

    public function getImageName(): ?string
    {
        return $this->imageName;
    }
}

Default
,

Merci Digivia ! je comprend mieux pourquoi maintent ^^. Je vais suivre ton conseil et refaire une Entity a coté.

Default
,

Je comprend pas...
j'ai essayé ta méthode @Digivia ( "laisser mon entité User avec les données minimales d'authentification, et créer une entité Profile liée en OneToOne" )

mais j'ai toujours la même erreur !

"Serialization of 'Symfony\Component\HttpFoundation\File\File' is not allowed"

Mon controller :

/**
     * @Route(path="profile/info-personnel/test", name="profile.test")
     * @param Request $request
     * @param ProfileRepository $profileRepository
     * @return Response
     */
    public function profilePersonal(Request $request, ProfileRepository $profileRepository){

        $user = $this->getUser();
        $profile = $profileRepository->findOneBy(['user' => $user]);

        $form = $this->createForm(ProfileType::class, $profile);
        $form->handleRequest($request);


        return $this->render('profile/info/personnel-test.html.twig', [
            'current_menu' => 'profile',
            'current_menu_profile' => 'info',
            'current_submenu_profile' => 'personnel',
            'form' => $form->createView(),
        ]);
    }

Mon FormType :

<?php

namespace App\Form\User;

use App\Entity\Profile;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Vich\UploaderBundle\Form\Type\VichImageType;

class ProfileType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('firstName')
            ->add('lastName')
            ->add('imageFile', VichImageType::class,[
                'required' => false
            ])
//            ->add('user')
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Profile::class,
        ]);
    }
}

Mon Entity :

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
 * @ORM\Entity(repositoryClass="App\Repository\ProfileRepository")
 * @Vich\Uploadable()

 */
class Profile
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\OneToOne(targetEntity="App\Entity\User", inversedBy="profile", cascade={"persist", "remove"})
     * @ORM\JoinColumn(nullable=false)
     */
    private $user;

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

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

    /**
     * @ORM\Column(type="boolean")
     */
    private $verified;

    /**
     * @ORM\Column(type="datetime")
     */
    private $modifiedAt;

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

    /**
     * NOTE: This is not a mapped field of entity metadata, just a simple property.
     * @Vich\UploadableField(mapping="avatars_images", fileNameProperty="imageName")
     * @var File
     */
    private $imageFile;


    public function __construct()
    {
        $this->modifiedAt = new \DateTime('now');
        $this->verified = 0;
        $this->imageName = 'empty.png';
    }

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

    public function getUser(): ?User
    {
        return $this->user;
    }

    public function setUser(User $user): self
    {
        $this->user = $user;

        return $this;
    }

    public function getFirstName(): ?string
    {
        return $this->firstName;
    }

    public function setFirstName(?string $firstName): self
    {
        $this->firstName = $firstName;

        return $this;
    }

    public function getLastName(): ?string
    {
        return $this->lastName;
    }

    public function setLastName(?string $lastName): self
    {
        $this->lastName = $lastName;

        return $this;
    }

    public function getVerified(): ?bool
    {
        return $this->verified;
    }

    public function setVerified(bool $verified): self
    {
        $this->verified = $verified;

        return $this;
    }

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

    public function setModifiedAt(\DateTimeInterface $modifiedAt): self
    {
        $this->modifiedAt = $modifiedAt;

        return $this;
    }

    /**
     * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
     * of 'UploadedFile' is injected into this setter to trigger the update. If this
     * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
     * must be able to accept an instance of 'File' as the bundle will inject one here
     * during Doctrine hydration.
     *
     * @param File|UploadedFile $imageFile
     * @return Profile
     * @throws \Exception
     */
    public function setImageFile(?File $imageFile = null): Profile
    {
        $this->imageFile = $imageFile;
        if ($this->imageFile instanceof UploadedFile) {
            $this->modifiedAt = new \DateTime('now');
        }
        return $this;
    }

    public function getImageFile(): ?File
    {
        return $this->imageFile;
    }

    public function setImageName(?string $imageName): void
    {

        $this->imageName = $imageName;
    }

    public function getImageName(): ?string
    {
        return $this->imageName;
    }
}

Default
,

Yehhh Un grand merci @Digivia ! ça fonction parfaitement ^^.
Par contre j'ai du mal a comprendre a quoi sert ce Serialisable :/ meme avec la doc...

87112
,

Ton entité est sérialisée car elle est liée à User. C'est le process de sécurité de symfony qui gère ça en automatique. Pour plus d'infos, va voir ce lien: https://symfony.com/doc/2.4/cookbook/security/entity_provider.html#the-data-model

"What is the importance of serialize and unserialize?

The Serializable interface and its serialize and unserialize methods have been added to allow the User class to be serialized to the session. This may or may not be needed depending on your setup, but it's probably a good idea. The id is the most important value that needs to be serialized because the refreshUser() method reloads the user on each request by using the id. In practice, this means that the User object is reloaded from the database on each request using the id from the serialized object. This makes sure all of the User's data is fresh.

Symfony also uses the username, salt, and password to verify that the User has not changed between requests. Failing to serialize these may cause you to be logged out on each request. If your User implements EquatableInterface, then instead of these properties being checked, your isEqualTo method is simply called, and you can check whatever properties you want. Unless you understand this, you probably won't need to implement this interface or worry about it."

Dans le cas d'un upload de photo, il faut indiquer que la sérialisation ne concerne pas l'élément uploadé (uniquement le nom du fichier) pour ne pas avoir d'erreur. Dans l'absolu, il faudrait même ne serialiser que les éléments nécessaires à la sécurité, mais ça fonctionne très bien avec la méthode que je t'ai donné ;)

Default
,

Super ! cette fois c'est claire ^^. MERCI !

Default
,

Une derniere petite chose. Comment mettre une image part defaut ?
J'ai pas eu de probleme a le faire pour l'avatar avec le Constructeur. Par contre quand j'utilise la case à cocher "supprimer ?", forcement j'ai plus d'image par defaut. Y a t'il un moyen simple pour le faire ?

87112
,

Tu peux le faire via une méthode de ton entité, ou dans le getter de l'image... Mais c'est en dur dans ton code (même avec une constante).
Ou alors dans ton template twig via une condition, c'est la solution que je privilégie généralement, si un intégrateur a besoin de travailler sur ton projet, il comprend de suite ton code...

Default
,

Merci du coup j'ai repris la methode de twig que je connaisais deja et qui fonctionne très bien.

Par contre j'ai de nouveau un souci :/

Je comprend pas pourquoi je n'arrive pas a Uploader de fichier pour mes articles.. J'ai aucun message d'erreur. Et pourtant rien ne s'enregistre dans ma base de donner ni dans ImageName ni dans Modified_at.

Je mets mon code dans le doute ou je suis passeé a cote de quelque chose.

Entity :

<?php

namespace App\Entity;

use Cocur\Slugify\Slugify;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
 * @ORM\Entity(repositoryClass="App\Repository\PostRepository")
 * @UniqueEntity("title")
 * @UniqueEntity("description")
 * @Vich\Uploadable()
 */
class Post
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

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

    /**
     * @ORM\Column(type="text")
     */
    private $description;

    /**
     * @ORM\Column(type="datetime")
     */
    private $createdAt;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Category", inversedBy="posts")
     * @ORM\JoinColumn(nullable=false)
     */
    private $category;

    /**
     * @ORM\Column(type="datetime")
     */
    private $modifiedAt;

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

    /**
     * @ORM\Column(type="boolean")
     */
    private $highlighted;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="post")
     */
    private $comments;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="posts")
     * @ORM\JoinColumn(nullable=false)
     */
    private $user;


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

    /**
     * NOTE: This is not a mapped field of entity metadata, just a simple property.
     * @Vich\UploadableField(mapping="posts_images", fileNameProperty="imageName")
     * @var File
     */
    private $imageFile;


    public function __construct()
    {
        $this->createdAt = new \DateTime('now');
        $this->modifiedAt = new \DateTime('now');
        $this->status = 'Brouillon';
        $this->comments = new ArrayCollection();
    }

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

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function setTitle(string $title): self
    {
        $this->title = $title;
        $this->setModifiedAt(new \DateTime('now'));

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(string $description): self
    {
        $this->description = $description;
        $this->setModifiedAt(new \DateTime('now'));

        return $this;
    }


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

    public function setCreatedAt(\DateTimeInterface $createdAt): self
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    public function getSlug()
    {
        $slugify = new Slugify();
        return $slugify->slugify($this->title);
    }

    public function getCategorySlug(string $category)
    {
        $slugify = new Slugify();
        return $slugify->slugify($category);
    }

    public function getCategory(): ?Category
    {
        return $this->category;
    }

    public function setCategory(?Category $category): self
    {
        $this->category = $category;
        $this->setModifiedAt(new \DateTime('now'));

        return $this;
    }

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

    public function setModifiedAt(\DateTimeInterface $modifiedAt): self
    {
        $this->modifiedAt = $modifiedAt;

        return $this;
    }

    public function getStatus(): ?string
    {
        return $this->status;
    }

    public function setStatus(string $status): self
    {
        $this->status = $status;
        $this->setModifiedAt(new \DateTime('now'));

        return $this;
    }

    public function getHighlighted(): ?bool
    {
        return $this->highlighted;
    }

    public function setHighlighted(?bool $highlighted): self
    {
        $this->highlighted = $highlighted;

        return $this;
    }

    /**
     * @return Collection|Comment[]
     */
    public function getComments(): Collection
    {
        return $this->comments;
    }

    public function addComment(Comment $comment): self
    {
        if (!$this->comments->contains($comment)) {
            $this->comments[] = $comment;
            $comment->setPost($this);
        }

        return $this;
    }

    public function removeComment(Comment $comment): self
    {
        if ($this->comments->contains($comment)) {
            $this->comments->removeElement($comment);
            // set the owning side to null (unless already changed)
            if ($comment->getPost() === $this) {
                $comment->setPost(null);
            }
        }

        return $this;
    }

    public function getUser(): ?User
    {
        return $this->user;
    }

    public function setUser(?User $user): self
    {
        $this->user = $user;

        return $this;
    }

    /**
     * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
     * of 'UploadedFile' is injected into this setter to trigger the update. If this
     * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
     * must be able to accept an instance of 'File' as the bundle will inject one here
     * during Doctrine hydration.
     *
     * @param File|UploadedFile $imageFile
     * @return Post
     * @throws \Exception
     */
    public function setImageFile(?File $imageFile = null): Post
    {
        $this->imageFile = $imageFile;
        if ($this->imageFile instanceof UploadedFile) {
            $this->modifiedAt = new \DateTime('now');
        }
        return $this;
    }

    public function getImageFile(): ?File
    {
        return $this->imageFile;
    }

    public function setImageName(?string $imageName): void
    {
        $this->imageName = $imageName;
    }

    public function getImageName(): ?string
    {
        return $this->imageName;
    }
}

FormType :

<?php

namespace App\Form\Post;

use App\Entity\Category;
use App\Entity\Post;
use App\Entity\User;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Vich\UploaderBundle\Form\Type\VichImageType;


class ActualityType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('description', TextareaType::class, [
                'attr' => [
                    'rows' => 10,
                ]])
            ->add('highlighted')
//            ->add('image')
            ->add('category', EntityType::class, [
                'class' => Category::class,
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('c');
                },
                'choice_label' => 'name'
            ])
            ->add('user', EntityType::class, [
                'class' => User::class,
                'query_builder' => function (EntityRepository $repository) {
                    return $repository->createQueryBuilder('u');
                },
                'choice_label' => 'username'
            ])
            ->add('publish', SubmitType::class, [
                'label' => 'Publier',
                'attr' => [
                    'class' => 'btn-success btn-block'
                ]
            ])
            ->add('draft', SubmitType::class, [
                'label' => 'Brouillon',
                'attr' => [
                    'class' => 'btn-warning btn-block'
                ]
            ])
            ->add('delete', SubmitType::class, [
                'label' => 'Supprimer',
                'attr' => [
                    'class' => 'btn-danger btn-block'
                ]
            ])
            ->add('imageFile', VichImageType::class, [
                'required' => false,
                'download_link' => false,
                'image_uri' => false
            ]);
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Post::class,
            'translation_domain' => 'forms'
        ]);
    }
}

Controller :

/**
     * @Route(path="admin/actualites/edit/{slug}-{id}", name="admin.actuality.edit", requirements={"slug": "[a-z0-9\-]*" })
     * @param Request $request
     * @param Post $post
     * @return Response
     */
    public function edit(Request $request, Post $post){

        $form = $this->createForm(ActualityType::class, $post);
        $form->handleRequest($request);

        if ($form->get('publish')->isClicked()) {
            $post->setStatus('Publier');
        }elseif($form->get('draft')->isClicked()){
            $post->setStatus('Brouillon');
            $post->setHighlighted(0) ;
        }elseif($form->get('delete')->isClicked()){
            $post->setStatus('Supprimer');
            $post->setHighlighted(0) ;
        }

        if ($form->isSubmitted() && $form->isValid()) {
            $this->manager->flush();
            $this->addFlash('success', 'Article modifié avec succes');

            return $this->redirectToRoute('admin.actuality');
        }

        return $this->render('admin/admin_actuality/edit.html.twig', [
            'current_menu' => 'admin',
            'current_menu_admin' => 'actualites',
            'form_actuality' => $form->createView()
        ]);