Bonjour,

Voilà je rencontre un petit problème lors de l'envois de fichier via VichUploaderBundle.

J'ai déjà une entity "Profile" qui possède la possibilité d'envoyer une image pour l'avatar et qui fonctionne très bien.
Mais voilà quand j'ai voulu ajouter la possibilité d'ajouter une image sur un Post celle-ci n'est carrément pas pris en compte. Je n'ai aucun message d'erreur, on dirait que la function setImageFile n'est pas mis à jour lors de l'envoie des informations dans la BBD.
Voici mon code :

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()
        ]);

3 réponses


aka-aka
Auteur
Réponse acceptée

j'ai trouvé mon problème. Je met la solution si quelqu'un est dans le même cas que moi.

Le souici était un oubli de ma pars dans le fichier de rendu .twig.

J'avais oublié d'ajouter le enctype="multipart/form-data

            <form method="post" enctype="multipart/form-data">
            ...
                .....
                ......
            ...
            </form>

Hello,
J'ai exactement le même problème que toi. Par contre je ne comprends pas comment tu as fait pour changer l'enctype de ton form.
Est-ce que tu peux me partager ton formulaire pour que je comprenne ?
Le mien est construit ainsi :

 {{ form_start(formAlbum)}}

            {{ form_row(formAlbum.coverName, {'attr': {'placeholder': "Image de couverture"}}) }}
            {{ form_row(formAlbum.title, {'attr': {'placeholder': "Titre de l'album"}}) }}
            {{ form_row(formAlbum.subtitle, {'attr': {'placeholder': "Sous-titre de l'album"}}) }}
            {{ form_row(formAlbum.scenario, {'attr': {'placeholder': "Scénariste"}}) }}
            {{ form_row(formAlbum.dessin, {'attr': {'placeholder': "Déssinateur"}}) }}
            {{ form_row(formAlbum.Couleur, {'attr': {'placeholder': "Coloriste"}}) }}
            {{ form_row(formAlbum.date) }}
            {{ form_row(formAlbum.content, {'attr': {'placeholder': "Texte de présentation"}}) }}
            {{ form_row(formAlbum.buyLink, {'attr': {'placeholder': "Lien Bamboo de vente"}}) }}

            <button class="btn btn-primary" type="submit">
                {% if editMode %}
                    Modifier
                {% else %}
                    Publier
                {% endif %}
        </button>

        {{ form_end(formAlbum) }}
aka-aka
Auteur

avant ton { form_start() } place :

<form method="post" enctype="multipart/form-data">