3

I'm beginning with Symfony and I'm stuck with multiple upload.

I can upload just one file and I try to modify this code for multiple upload.

Here's my error :

Expected argument of type "Symfony\Component\HttpFoundation\File\UploadedFile", "array" given

Here's my code :

ImageArticleType:

$builder
        ->add('file', 'file', array('label' => 'Choisir mes images', 'multiple'=> true))
    ;

And my Entity ImageArticle.php

<?php

namespace AD\PlatformBundle\Entity;

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

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

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

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

    /**
     * @var File
     *  
     * @Assert\File(
     *     maxSize = "1M",
     *     mimeTypes = {
     *          "image/jpeg", 
     *          "image/gif", 
     *          "image/png", 
     *          },
     *     maxSizeMessage = "La taille maximum du fichier doit etre inférieur ou égale à 1MB. Pour reduire sa taille vous pouvez utiliser le site : compressjpeg.com",
     *     mimeTypesMessage = "Seulement les fichiers .jpeg / .gif /.png sont acceptés"
     * )
     */
    private $file;

    private $tempFileName;

    public function getFile()
    {   
        return $this->file;
    }

    public function setFile(UploadedFile $file)
    {

        $this->file = $file;

        if (null !== $this->url)
        {
            $this->tempFileName = $this->url;
            $this->url=null;
            $this->alt=null;
        }
    }
    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set url
     *
     * @param string $url
     *
     * @return ImageArticle
     */
    public function setUrl($url)
    {
        $this->url = $url;

        return $this;
    }

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

    /**
     * Set alt
     *
     * @param string $alt
     *
     * @return ImageArticle
     */
    public function setAlt($alt)
    {
        $this->alt = $alt;

        return $this;
    }

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

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function preUpload()
    {
        if (null === $this->file)
        {
            return;
        }


        //On add un extension pour le fichier.
        $this->url = $this->file->guessExtension();
        //Le alt est le nom du fichier du client.
        $this->alt=  $this->file->getClientOriginalName();

    }

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

        //Si ancien fichier on supprime
        if(null !== $this->tempFileName)
        {
            $oldFile = $this->getUploadRootDir().'/'.$this->id.'.'.$this->tempFileName;
            if (file_exists($oldFile))
            {
                unlink($oldFile);
            }
        }

        //On deplace
        $this->file->move
        (
            $this->getUploadRootDir(),
            $this->id.'.'.$this->url    
        );
    }

    /**
     *@ORM\PreRemove()
     */
    public function preRemoveUpload()
    {
        $this->tempFileName = $this->getUploadRootDir().'/'.$this->id.'.'.$this->url;
    }

    /**
     * 
     * @ORM\PostRemove()
     */
    public function removeUpload()
    {
        if(file_exists($this->tempFileName))
        {
            unlink($this->tempFileName);
        }
    }
    public function getUploadDir()
    {
        return 'upload/img/';
    }

    protected function getUploadRootDir()
    {
        return __DIR__.'/../../../../web/'.$this->getUploadDir();
    }

    public function __toString()
    {
        return $this->getUploadDir().$this->id.'.'.$this->getUrl();
    }

    /**
     * Set source
     *
     * @param string $source
     *
     * @return Image
     */
}

I was thinking about a simple foreach loop but it doesn't work...

6
  • Your error is telling you that you try to pass an array instead of an item of class UploadedFile. Try to remove the multiple options from your field, this may render an array instead. Commented Aug 8, 2016 at 15:47
  • Thx for your response ! If I remove the multiple option I can't select more than one file. Commented Aug 8, 2016 at 15:56
  • Yes I know, but try if you still get the error with only one file. If not your code is correct and i think you should try to make a foreach loop in you controller, to save each file alone. Commented Aug 8, 2016 at 15:58
  • Oh ok. Yes with only one file it work fine. In my controller I persist/flush my Article. I try to have more than one picture with my article so in ArticleType I call ImageArticleType like this ->add('imagearticle', new ImageArticleType(), array('required' => true)). Can't I make a foreach into my ImageArticle Entity ? Commented Aug 8, 2016 at 16:05
  • No, inside your controller, look the answer below Commented Aug 8, 2016 at 16:07

3 Answers 3

1

Uploading files with multiple option can be a little bit tricky. With multiple = false option your $file property in your entity class will return single UploadedFile instance, with multiple = true it returns array of UploadedFile instances when you call $entity->getFile(). That's why you have to implement the upload process manually, on form submission, in your action, without lifecycle callbacks. Like this:

Action:

....
$image = new ImageArticle();

$form = $this->createForm('YOUR_FORM', $image);
$form->handleRequest($request);

if ($form->isValid()) {
    ...

    foreach ($image->getFile() as $uploadedFile) {
        $image = new ImageArticle();
        $image
            // setters go here
        ;

        // Upload process go here

        $image->setFile(null);
    }

    $this->get('doctrine.orm.entity_manager')->flush();

    ....
}

Here is a screenshot from my project: enter image description here

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

3 Comments

I've got this error Type error: Argument 3 passed to Symfony\Component\Form\FormFactory::create() must be of the type array, object given, called in /var/www/html/QrCar/src/AD/PlatformBundle/Controller/CarsController.php on line 296
This error is telling you that the $image param of your $this->get('form.factory')->create() in an object instead of an array. Is your images are save in the article entity or another ?
@Wako createForm() method receives ('String formTypeName', Object dataObject, Array options), I think you're passing an object as a third parameter. Read this
0

Something like that ?

public function newArticleAction(Request $request)
{
   $article = new Article();
   $article->setUser($this->getUser());

   $imageArticle = new ImageArticle();

   $form = $this->get('form.factory')->create(new \AD\PlatformBundle\Form\ArticleType(), $article, $image); 
    if($form->handleRequest($request)->isValid())
    {
        foreach($imageArticle->getFile() as $imageArticle)
        {
            $imageArticle = new ImageArticle();

            $imageArticle->setAlt($imageArticle->getAlt());
            $imageArticle->setUrl($imageArticle->getUrl());
            $imageArticle->setFile($imageArticle->getFile());

            $imageArticle->preRemoveUpload();
            $imageArticle->preUpload();
            $imageArticle->upload();

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

        $request->getSession()->getFlashBag()->add('notice', 'Article publié ! :)');
        return $this->redirect($this->generateUrl('va_platform_blog'));
    }
    return $this->render('ADPlatformBundle:Cars:newarticle.html.twig', array(
        'form' =>$form->createView(),
    ));
}

Comments

0

Is your images are save in the article entity or another (I'll make changes when I get your answer) ?

I have made some little changes to your code. I'm not sure about all the code but I think this should work

public function newArticleAction(Request $request)
{
   $article = new Article();
   $images = new ImageArticle();

   $form = $this->get('form.factory')->create(ArticleType::class, $article, $images);
   $form->handleRequest($request);

   if($form->isValid())
   {
       $article->setUser($this->getUser());
       // other article fields, if needed

       foreach($images->getFile() as $image)
       {
           $images->setAlt($image->getAlt());
           $images->setUrl($image->getUrl());
           $images->setFile($image->getFile());

           $images->preRemoveUpload();
           $images->preUpload();
           $images->upload();
       }

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

       $request->getSession()->getFlashBag()->add('notice', 'Article publié ! :)');

       return $this->redirect($this->generateUrl('va_platform_blog'));
    }

    return $this->render('ADPlatformBundle:Cars:newarticle.html.twig', [
        'form' => $form->createView(),
    ]);
}

12 Comments

I've got two entity : Article.php and ImageArticle.php
Same error. Type error: Argument 3 passed to Symfony\Component\Form\FormFactory::create() must be of the type array, object given
During the submit or at the page loading ?
During the page loading
Can you dump the $images in the $form->isValid() ? If this do not work comment the foreach
|

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.