I'm trying to follow this tutorial https://symfony.com/doc/current/controller/upload_file.html and it's nice and works, but I need to upload multiple files.
Right now I have 2 related tables Products and ProductImages. I know how to upload multiple files in controller, but I want it in doctrine, I think it's more clean and professional.
So I tried a lot of combinations with foreach but've always got an error:
Expected argument of type "Web\BaseBundle\Entity\ProductImages", "Symfony\Component\HttpFoundation\File\UploadedFile" given
My entities:
Products:
class Product
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
///
/**
* @ORM\OneToMany(targetEntity="Web\BaseBundle\Entity\ProductImages", mappedBy="product", cascade={"persist", "remove"})
* @ORM\OrderBy({"id" = "ASC"})
*
*/
private $images;
public function __toString(): string
{
return $this->getTitle();
}
/**
* Constructor
*/
public function __construct()
{
$this->images = new \Doctrine\Common\Collections\ArrayCollection();
}
////
/**
* Add image
*
* @param \Web\BaseBundle\Entity\ProductImages $image
*
* @return Product
*/
public function addImage(\Web\BaseBundle\Entity\ProductImages $image)
{
$this->images[] = $image;
return $this;
}
/**
* Remove image
*
* @param \Web\BaseBundle\Entity\ProductImages $image
*/
public function removeImage(\Web\BaseBundle\Entity\ProductImages $image)
{
$this->images->removeElement($image);
}
/**
* Get images
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getImages()
{
return $this->images;
}
}
ProductImages:
class ProductImages
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* @ORM\Column(name="image", type="string", length=255, nullable=true)
* @Assert\NotBlank(message="Please, upload the product brochure as a PDF file.")
* @Assert\File(mimeTypes={ "image/jpeg", "image/jpg", "image/png" })
*/
private $image;
///
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
///
/**
* Set image
*
* @param string $image
*
* @return ProductImages
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* @return string
*/
public function getImage()
{
return $this->image;
}
}
FileUploader:
class FileUploader
{
private $targetDir;
public function __construct($targetDir)
{
$this->targetDir = $targetDir;
}
public function upload(UploadedFile $file)
{
$fileName = md5(uniqid()).'.'.$file->guessExtension();
$file->move($this->getTargetDir(), $fileName);
return $fileName;
}
public function getTargetDir()
{
return $this->targetDir;
}
}
FileUploadListener:
class FileUploadListener
{
private $uploader;
public function __construct(FileUploader $uploader)
{
$this->uploader = $uploader;
}
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$this->uploadFile($entity);
}
public function preUpdate(PreUpdateEventArgs $args)
{
$entity = $args->getEntity();
$this->uploadFile($entity);
}
private function uploadFile($entity)
{
//Tried a lot of combinations with foreach, but not working :(
if (!$entity instanceof Product) {
return;
}
$file = $entity->getImages();
// only upload new files
if (!$file instanceof UploadedFile) {
return;
}
$fileName = $this->uploader->upload($file);
$entity->setImages($fileName);
}
}
Could someone help me with this? Thanks