6

UPDATED In my Symfony project,I am able to upload single image.Now I am trying to upload multiple images.

class ImageFile extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('images', FileType::class, array(
                'attr' => array(
                    'accept' => 'image/*',
                    'multiple' => 'multiple'
                )
            ))
            ->add('save',SubmitType::class,array('label'=>'Insert Image','attr'=>array('class'=>'btn btn-primary','style'=>'margin-bottom:15px')))
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => images::class
        ));
    }
}

In my Images entity, I keep an array of SatellieImage objects like this.

class images
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @var satelliteImage[]
     * @ORM\Column(name="images", type="string")
     *
     */
    private $images;

    /**
     * Set images
     *
     * @param string $images
     *
     * @return satelliteImage[]
     */
    public function setImages($images)
    {
        $this->images = $images;

        return $this->images;
    }

    /**
     * Get images
     *
     * @return satelliteImage[]
     */
    public function getImages()
    {
        return $this->images;
    }

    public function addImage($image)
    {
        $this->images[] = $image;

        return $this;
    }
}

And in my controller, I store the satelliteImage[] as $files and run a foreach loop to upload() each file (upload() function worked perfectly for single file)

public function uploadImages(Request $request)
    {
        $satelliteImage=new satelliteImage;
        $images=new images();

        $form = $this->createForm(ImageFile::class, $images);
        $form->handleRequest($request);

        $files=$images->getImages();

        foreach ($files as $file){
            $em=$this->getDoctrine()->getManager();

            $file->upload();

            $em->persist($satelliteImage);
            $em->flush();
        }
        $this->addFlash(
            'notice',
            'Images inserted successfully'
        );

        return $this->redirectToRoute('satellite_images');
    }

Problem : I get an error saying "Warning: Invalid argument supplied for foreach()" How do I fix this?

3
  • So you haven't really read the answer posted below? Commented Jan 12, 2017 at 8:44
  • 1
    @Fyntasia, I did read that, but the problem is I have a different issue now. The 'Browse images' button does not appear....It probably might work if this issue is solved. Commented Jan 12, 2017 at 8:50
  • 1
    @MadhukaHarith Did you figure it out? Because I have the same problem, I can upload single image, but not multiple. Commented Jul 29, 2017 at 11:07

3 Answers 3

13

I think all you have to do here is add the 'multiple' attribute to your ImageFile class;

See Symfony documentation.

use Symfony\Component\Form\Extension\Core\Type\FileType;

class ImageFile extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('images', FileType::class, [
                'multiple' => true,
                'attr'     => [
                    'accept' => 'image/*',
                    'multiple' => 'multiple'
                ]
            ])
        ;
    }
}

Also, change your 'image' property, to 'images' property:

/**
 * Set images
 *
 * @param string $images
 *
 * @return satelliteImage[]
 */
public function setImages($images)
{
    $this->images = $images;

    return $this;
}

/**
 * Get images
 *
 * @return string
 */
public function getImages()
{
    return $this->image;
}

public function addImage($image)
{
    $this->images[] = $image;

    return $this;
}

Once you have this sorted, you can modify your upload method to handle multiple files from the FormType.

Sign up to request clarification or add additional context in comments.

7 Comments

I did that but still I get an error saying Could not load type "file"
Ah yes, I see. I've edited my post. Try passing the FileType this way.
Really appreciate your help, but after making that change I get an error saying Expected argument of type "string", "Symfony\Component\Form\Extension\Core\Type\FileType" given
Which version of Symfony are you using? When looking at the symfony documentation, the 'file' string declaration should work. The problem you're having could be unrelated to the formtype.
I am using Symfony 3.2.1
|
3

Maybe working example help you? I make simple app with multipe file upload for symfony 3.*. Here is link: https://github.com/marekz/example_symfony_multiply_files_example

First: Both form declatartion:

    <?php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use AppBundle\Form\FilesType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;

class UserType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('name')
                ->add('lastName')
                ->add('files', CollectionType::class,array(
                    'entry_type' => FilesType::class,
                    'allow_add' => true,
                    'by_reference' => false,
                ))
                ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\User'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_user';
    }


}


    <?php

namespace AppBundle\Form;

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

class FilesType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('file');
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Files'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_files';
    }


}

Now, my entities:

<?php

namespace AppBundle\Entity;

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

/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 */
class User {

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

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

    /**
     * @ORM\ManyToMany(targetEntity="Files", cascade={"persist"})
     */
    private $files;

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

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

    /**
     * Set name
     *
     * @param string $name
     *
     * @return User
     */
    public function setName($name) {
        $this->name = $name;

        return $this;
    }

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

    /**
     * Set lastName
     *
     * @param string $lastName
     *
     * @return User
     */
    public function setLastName($lastName) {
        $this->lastName = $lastName;

        return $this;
    }

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

    /**
     * Get files
     * 
     * @return ArrayCollection
     */
    function getFiles() {
        return $this->files;
    }

    /**
     * Set files
     * @param type $files
     */
    function setFiles($files) {
        $this->files = $files;
    }
}

    <?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

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

    /**
     * @var string
     *
     * @ORM\Column(name="file", type="string", length=255, unique=true)
     * @Assert\NotBlank(message="Please, upload the product brochure as a PDF file.")
     * @Assert\File(mimeTypes={ "application/pdf" })
     */
    private $file;

    /**
     *
     * @return Files
     */
    function getUser() {
        return $this->user;
    }

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

    /**
     * Set file
     *
     * @param string $file
     *
     * @return Files
     */
    public function setFile($file)
    {
        $this->file = $file;

        return $this;
    }

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

Finaly, Symfony Controller:

/**
 * Creates a new user entity.
 *
 * @Route("/new", name="user_new")
 * @Method({"GET", "POST"})
 */
public function newAction(Request $request) {
    $user = new User();
    $form = $this->createForm('AppBundle\Form\UserType', $user);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {

        $attachments = $user->getFiles();

        if ($attachments) {
            foreach($attachments as $attachment)
            {
                $file = $attachment->getFile();

                var_dump($attachment);
                $filename = md5(uniqid()) . '.' .$file->guessExtension();

                $file->move(
                        $this->getParameter('upload_path'), $filename
                );
                var_dump($filename);
                $attachment->setFile($filename);
            }
        }

        $em = $this->getDoctrine()->getManager();
        $em->persist($user);
        $em->flush();

        return $this->redirectToRoute('user_show', array('id' => $user->getId()));
    }

    return $this->render('user/new.html.twig', array(
                'user' => $user,
                'form' => $form->createView(),
    ));
}

1 Comment

Thanks. Of course, you have right. I correct my message in this moment.
3

I found this article that explain every detail in this question in symfony 5. I was very helpful to understand what is going on. If you are new, you can start here, then read question and you will sync.

The article: https://nouvelle-techno.fr/actualites/live-coding-upload-dimages-multiples-avec-symfony-4-et-5

Credit goes to Nouvelle-Techno.fr

The article is in french, please click on translate this page on your url bar if you are using chrome to translate to English.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.