1

[Update]: I resolved my problem ><, probably when i have done refactoring i left an ":?string" on my method getFile ...

Today i tried to add VichUploderBundle in my project, but i have encountered some trouble. I have follow the documentation but i don't like the way to make one property uploadable (add 3 properties on the same model just for that, excuse me but that not much pretty) So i started to create an Entity just for Image with all property necessary, I also created a new FormType and link all to my Parent Entity. But now when i try to post my form i get this error :

Return value of Vich\UploaderBundle\Mapping\PropertyMapping::getFile() must be an instance of Symfony\Component\HttpFoundation\File\File or null, string returned
(in vendor/vich/uploader-bundle/Mapping/PropertyMapping.php (line 80) )

I tried to add some dump to check the variable and she exist but for a strange reason Vich detects it as null.

Image Entity

<?php

namespace App\Entity;

use App\Entity\Traits\CreatedAtTrait;
use App\Entity\Traits\CreatedByTrait;
use Doctrine\ORM\Mapping as ORM;
use Exception;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
 * @ORM\Entity(repositoryClass="App\Repository\ImageRepository")
 * @Vich\Uploadable
 */
class Image
{
    use CreatedAtTrait;
    use CreatedByTrait;

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

    /**
     * @Vich\UploadableField(mapping="compose_logo", fileNameProperty="name", size="size")
     * @var File
     */
    private $file;

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

    /**
     * @ORM\Column(type="integer")
     */
    private $size;

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

    public function getFile(): ?string
    {
        return $this->file;
    }

    /**
     * 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|null $file
     * @return Image
     * @throws Exception
     */
    public function setFile(?File $file = null): self
    {
        $this->file = $file;

        return $this;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getSize(): ?int
    {
        return $this->size;
    }

    public function setSize(int $size): self
    {
        $this->size = $size;

        return $this;
    }
}

ImageType

<?php

namespace App\Form;

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

class ImageType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('file', VichImageType::class, [
                'required' => false,
            ])
        ;
    }

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

Parent Entity

<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\ParentRepository")
 */
class Parent
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

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

    /**
     * @ORM\OneToOne(targetEntity="App\Entity\Image", cascade={"persist", "remove"})
     */
    private $logo;

    public function __construct()
    {
        $this->variables = new ArrayCollection();
    }

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

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }


    public function getLogo(): ?Image
    {
        return $this->logo;
    }

    public function setLogo(?Image $logo): self
    {
        $this->logo = $logo;

        return $this;
    }
}

ParentType

<?php

namespace App\Form;

use App\Entity\Parent;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ParentType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('logo', ImageType::class)
            ->add('name', TextType::class)
        ;
    }

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

And for the test i also tried to remove the annotations in vendor/vich/uploader-bundle/Mapping/PropertyMapping.php to accept all variable type and when Doctrine try to save the entity in the database all property in my Image entity is null except my createdAt trait (but that probably normal since i have exception before that ...)

Also there is a screenshot when i dump the variable at line 80 in vendor/vich/uploader-bundle/Mapping/PropertyMapping.php : https://i.stack.imgur.com/MJh2g.jpg

NSBX
  • 11
  • 6

1 Answers1

0

You need to define your 'logo' property as an EntityType in your ParentType class and not an ImageType ! So change this line ->add('logo', ImageType::class)

You've got example in the symfony doc : https://symfony.com/doc/current/reference/forms/types/entity.html

A. Ecrubit
  • 561
  • 6
  • 20
  • ImageType is my custom formType, i can't use an EntityType because i don't need a choice list but an vich file input (like the code in my ImageType) – NSBX Jun 09 '19 at 17:03