Multiple File Uploads with Symfony 3
<p>I have had my head burning for two days and I don't know where to run to: I need to upload multiple images for an object.</p>

<p>Mind you, I have an entity called REALTY, for which I can upload one OR more images. So I came up with this entity:</p>

<pre><code>&lt;?php

namespace AppBundle\Entity;

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

/**
 * Realty
 *
 * @ORM\Table(name="realty")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\RealtyRepository")
 */
class Realty extends Timestampable
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

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

    /**
     * @var string
     *
     * @ORM\Column(name="price", type="decimal", precision=8, scale=2)
     */
    private $price;

    /**
     * @var Advertiser
     *
     * @ORM\ManyToOne(targetEntity="Advertiser", inversedBy="realties")
     * @ORM\JoinColumn(name="adivertiser_id", referencedColumnName="id", nullable=false)
     */
    private $advertiser;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="RealtyImage", mappedBy="realty")
     */
    private $images;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this-&gt;images = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this-&gt;id;
    }

    /**
     * Set title
     *
     * @param string $title
     *
     * @return Realty
     */
    public function setTitle($title)
    {
        $this-&gt;title = $title;

        return $this;
    }

    /**
     * Get title
     *
     * @return string
     */
    public function getTitle()
    {
        return $this-&gt;title;
    }

    /**
     * Set description
     *
     * @param string $description
     *
     * @return Realty
     */
    public function setDescription($description)
    {
        $this-&gt;description = $description;

        return $this;
    }

    /**
     * Get description
     *
     * @return string
     */
    public function getDescription()
    {
        return $this-&gt;description;
    }

    /**
     * Set price
     *
     * @param string $price
     *
     * @return Realty
     */
    public function setPrice($price)
    {
        $this-&gt;price = $price;

        return $this;
    }

    /**
     * Get price
     *
     * @return string
     */
    public function getPrice()
    {
        return $this-&gt;price;
    }

    /**
     * Set advertiser
     *
     * @param \AppBundle\Entity\Advertiser $advertiser
     *
     * @return Realty
     */
    public function setAdvertiser(\AppBundle\Entity\Advertiser $advertiser)
    {
        $this-&gt;advertiser = $advertiser;

        return $this;
    }

    /**
     * Get advertiser
     *
     * @return \AppBundle\Entity\Advertiser
     */
    public function getAdvertiser()
    {
        return $this-&gt;advertiser;
    }

    /**
     * Add image
     *
     * @param \AppBundle\Entity\RealtyImage $image
     *
     * @return Realty
     */
    public function addImage(\AppBundle\Entity\RealtyImage $image)
    {
        $this-&gt;images[] = $image;

        return $this;
    }

    /**
     * Remove image
     *
     * @param \AppBundle\Entity\RealtyImage $image
     */
    public function removeImage(\AppBundle\Entity\RealtyImage $image)
    {
        $this-&gt;images-&gt;removeElement($image);
    }

    /**
     * Get images
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getImages()
    {
        return $this-&gt;images;
    }
}
</code></pre>

<p>And then, I created another Entity to represent that one-to-many (realty has many images).</p>

<pre><code>&lt;?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * RealtyImage
 *
 * @ORM\Table(name="realty_image")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\RealtyImageRepository")
 */
class RealtyImage
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @var int
     *
     * @ORM\Column(name="realty", type="integer")
     */
    private $realty;

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


    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this-&gt;id;
    }

    /**
     * Set description
     *
     * @param string $description
     *
     * @return RealtyImage
     */
    public function setDescription($description)
    {
        $this-&gt;description = $description;

        return $this;
    }

    /**
     * Get description
     *
     * @return string
     */
    public function getDescription()
    {
        return $this-&gt;description;
    }

    /**
     * Set realty
     *
     * @param integer $realty
     *
     * @return RealtyImage
     */
    public function setRealty($realty)
    {
        $this-&gt;realty = $realty;

        return $this;
    }

    /**
     * Get realty
     *
     * @return int
     */
    public function getRealty()
    {
        return $this-&gt;realty;
    }

    /**
     * Set path
     *
     * @param string $path
     *
     * @return RealtyImage
     */
    public function setPath($path)
    {
        $this-&gt;path = $path;

        return $this;
    }

    /**
     * Get path
     *
     * @return string
     */
    public function getPath()
    {
        return $this-&gt;path;
    }
}
</code></pre>

<p>No problems up to here (I guess). But then I have the FormType. That's where things go wrong. If I declare it as: </p>

<pre><code>&lt;?php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class RealtyType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            -&gt;add('title')
            -&gt;add('description')
            -&gt;add('price')
            -&gt;add('images', FileType::class, [
                'multiple' =&gt; true,
            ])
            -&gt;add('advertiser')
        ;
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver-&gt;setDefaults(array(
            'data_class' =&gt; 'AppBundle\Entity\Realty'
        ));
    }
}
</code></pre>

<p>I'll get the following error: </p>

<blockquote>
  <p>The form's view data is expected to be an instance of class
  Symfony\Component\HttpFoundation\File\File, but is an instance of
  class Doctrine\Common\Collections\ArrayCollection. You can avoid this
  error by setting the "data_class" option to null or by adding a view
  transformer that transforms an instance of class
  Doctrine\Common\Collections\ArrayCollection to an instance of
  Symfony\Component\HttpFoundation\File\File.</p>
</blockquote>

<p>I'm completely lost here. I know I'm missing several concepts, but I don't know where to start looking, and I didn't even start the "handling the files" process, after I get the form to work.</p>

<p>Many thanks</p>