Reputation: 1286
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.
Mind you, I have an entity called REALTY, for which I can upload one OR more images. So I came up with this entity:
<?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->images = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* @param string $title
*
* @return Realty
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set description
*
* @param string $description
*
* @return Realty
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set price
*
* @param string $price
*
* @return Realty
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* Get price
*
* @return string
*/
public function getPrice()
{
return $this->price;
}
/**
* Set advertiser
*
* @param \AppBundle\Entity\Advertiser $advertiser
*
* @return Realty
*/
public function setAdvertiser(\AppBundle\Entity\Advertiser $advertiser)
{
$this->advertiser = $advertiser;
return $this;
}
/**
* Get advertiser
*
* @return \AppBundle\Entity\Advertiser
*/
public function getAdvertiser()
{
return $this->advertiser;
}
/**
* Add image
*
* @param \AppBundle\Entity\RealtyImage $image
*
* @return Realty
*/
public function addImage(\AppBundle\Entity\RealtyImage $image)
{
$this->images[] = $image;
return $this;
}
/**
* Remove image
*
* @param \AppBundle\Entity\RealtyImage $image
*/
public function removeImage(\AppBundle\Entity\RealtyImage $image)
{
$this->images->removeElement($image);
}
/**
* Get images
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getImages()
{
return $this->images;
}
}
And then, I created another Entity to represent that one-to-many (realty has many images).
<?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->id;
}
/**
* Set description
*
* @param string $description
*
* @return RealtyImage
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set realty
*
* @param integer $realty
*
* @return RealtyImage
*/
public function setRealty($realty)
{
$this->realty = $realty;
return $this;
}
/**
* Get realty
*
* @return int
*/
public function getRealty()
{
return $this->realty;
}
/**
* Set path
*
* @param string $path
*
* @return RealtyImage
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Get path
*
* @return string
*/
public function getPath()
{
return $this->path;
}
}
No problems up to here (I guess). But then I have the FormType. That's where things go wrong. If I declare it as:
<?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
->add('title')
->add('description')
->add('price')
->add('images', FileType::class, [
'multiple' => true,
])
->add('advertiser')
;
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Realty'
));
}
}
I'll get the following error:
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.
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.
Many thanks
Upvotes: 1
Views: 3840
Reputation: 2106
That error means exactly as it said, your are trying to create a form with a property images, declared of type FileType::class, so you are saying that is a single file, and in the entity "images" is declared as a collection; the attribute multiple=>true
don't resolve your problem.
For resolving this problem you must do what a lot of bundles do, create an entity containing one media or image, and then configure other entity in a OneToMany relations with the first. Then you must use embedded forms for add many images as you want.
Hope this help you
Upvotes: 3