0
votes

I'm trying to figure out how to do multiple file uploads but without luck. I have not been able to get too much info on this.. Maybe someone here will help me out? :D

Criteria:

I know that in my form type I'm supposed to use multiples for fields; but when I add it, it gives me the this error.

Catchable Fatal Error: Argument 1 passed to PhotoGalleryBundle\Entity\Image::setFile() must be an instance of Symfony\Component\HttpFoundation\File\UploadedFile, array given, called in /home/action/workspace/www/DecorInterior/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php on line 442 and defined Image Entity

Here is my code in PHP:

<?php

namespace PhotoGalleryBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * Image
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="PhotoGalleryBundle\Entity\ImageRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Image
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

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

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

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="imageUploadedDate", type="datetime")
     * @Gedmo\Timestampable(on="create")
     */
    private $imageUploadedDate;

    /**
     * @Assert\File(maxSize="6000000")
     */
    private $file;

    /**
     * @ORM\ManyToOne(targetEntity="Album", inversedBy="images")
     * @ORM\JoinColumn(name="album", referencedColumnName="id")
     */
    private $album;

    private $temp;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set imageCaptation
     *
     * @param string $imageCaptation
     * @return Image
     */
    public function setImageCaptation($imageCaptation)
    {
        $this->imageCaptation = $imageCaptation;

        return $this;
    }

    /**
     * Get imageCaptation
     *
     * @return string 
     */
    public function getImageCaptation()
    {
        return $this->imageCaptation;
    }

    /**
     * Set imageName
     *
     * @param string $imageName
     * @return Image
     */
    public function setImageName($imageName)
    {
        $this->imageName = $imageName;

        return $this;
    }

    /**
     * Get imageName
     *
     * @return string 
     */
    public function getImageName()
    {
        return $this->imageName;
    }

    /**
     * Set imageFilePath
     *
     * @param string $imageFilePath
     * @return Image
     */
    public function setImageFilePath($imageFilePath)
    {
        $this->imageFilePath = $imageFilePath;

        return $this;
    }

    /**
     * Get imageFilePath
     *
     * @return string 
     */
    public function getImageFilePath()
    {
        return $this->imageFilePath;
    }

    /**
     * Get imageUploadedDate
     *
     * @return \DateTime 
     */
    public function getImageUploadedDate()
    {
        return $this->imageUploadedDate;
    }

    /**
     * Set file.
     * 
     * @param UploadedFile $file
     */
    public function setFile(UploadedFile $file = null) {
        $this->file = $file;
        // check if we have an old image path
        if (isset($this->imageFilePath)) {
            // store the old name to delete after the update
            $this->temp = $this->imageFilePath;
            $this->imageFilePath = null;
        } else {
            $this->imageFilePath = 'initial';
        }
    }

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate
     */
    public function preUpload() {
        if (null !== $this->getFile()) {
            // do whatever you want to generate a unique name
            $fileName = sha1(uniqid(mt_rand(), true));
            $this->imageFilePath = $fileName . '.' . $this->getFile()->guessExtension();
        }
    }

    /**
     * @ORM\PostPersist()
     * @ORM\PostUpdate
     */
    public function upload() {
        if (null === $this->getFile()) {
            return;
        }

        // if there is an error when moving the file, an exception will
        // be automatically thrown by move(). This will properly prevent
        // the entity from being persisted to the database on error
        $this->getFile()->move($this->getUploadRootDir(), $this->imageFilePath);

        // check if we have an old image
        if (isset($this->temp)) {
            // delete the old image
            unlink($this->getUploadRootDir() . '/' . $this->temp);
            // clear the temp image path
            $this->temp = null;
        }

        $this->imageFilePath = null;
    }

    /**
     * @ORM\PostRemove()
     */
    public function removeUpload() {
        $file = $this->getAbsolutePath();
        if ($file) {
            unlink($file);
        }
    }

    /**
     * Get file.
     * 
     * @return UploadedFile
     */
    public function getFile() {
        return $this->file;
    }

    public function getAbsolutePath() {
        return null === $this->imageFilePath
            ? null
            : $this->getUploadRootDir() . '/' . $this->imageFilePath;
    }

    public function getWebPath() {
        return null === $this->imageFilePath
            ? null
            : $this->getUploadDir() . '/' . $this->imageFilePath;
    }
    public function getUploadRootDir() {
        // the absolute path where uploaded
        // documents should be saved
        return __DIR__.'/../../../web/' . $this->getUploadDir();
    }

    public function getUploadDir() {
        // get rid of the __DIR__ so it doesn't screw up
        // when displaying uploaded doc/image in the view
        return 'uploads/images';
    }

    /**
     * Set album
     *
     * @param \PhotoGalleryBundle\Entity\Album $album
     * @return Image
     */
    public function setAlbum(\PhotoGalleryBundle\Entity\Album $album = null)
    {
        $this->album = $album;

        return $this;
    }

    /**
     * Get album
     *
     * @return \PhotoGalleryBundle\Entity\Album 
     */
    public function getAlbum()
    {
        return $this->album;
    }
}

ImageType:

<?php

namespace PhotoGalleryBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ImageType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('imageCaptation')
            ->add('imageName')
            ->add('file', 'file', array('multiple' => TRUE))
            ->add('album')
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'PhotoGalleryBundle\Entity\Image'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'photogallerybundle_image';
    }
}
1

1 Answers

1
votes

In this case the value will be an array of UploadedFile objects. Given that you have a type with multiple files yet only one caption, name, etc I assume you will want to refactor Image to support multiple image files. In this case the file property would be better known as files and setFiles should accept an array.

If however you want have one Image entity per file uploaded, consider implementing a collection instead.

Alternatively you could manually process the form in your action. For example:

public function uploadAction(Request $request)
{
    foreach ($request->files as $uploadedFile) {
        $uploadedFile = current($uploadedFile['file']);
        // Build Image using each uploaded file
    }
    ...