0

Symfony3 with PhpStorm.2016.3.2

I succeeded in making a file uploader for one picture only. But now I need to make it "multiple"

I will show you the code and the error that comes up with it as I canno't upload multiple files.

here is the controller

public function newAction(Request $request)
{
    $restaurant = new Restaurant();
    $form = $this->createForm(RestaurantType::class, $restaurant);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $em = $this->getDoctrine()->getManager();

        // file upload
        if ($request->files->get('restaurant')['picture'] != null) {

            $file = $request->files->get('restaurant')['picture'];
            $targetDir = $this->getParameter('uploaded_restaurants');
            $filename = $this->get('app.uploader')->upload($file, $targetDir);
            $mediaRestaurant = null;
            if ($restaurant->getId() != null) {
                $mediaRestaurant = $this->getDoctrine()->getRepository('AppBundle:Media')->findPictureByRestaurant($restaurant);
            }
            if ($mediaRestaurant) {
                $media = $mediaRestaurant;
                $fs = new Filesystem();
                try {
                    $fs->remove($this->get('kernel')->getRootDir().'/../web/uploads/restaurants/'.$media->getName());
                } catch (IOException $e) {
                    echo "error";
                }
            } else {
                $media = new Media();
                $media->setCreatedAt(new \DateTime());
            }

            $originalName = $file->getClientOriginalName();
            $media->setName($filename)
                ->setOriginalName($originalName)
                ->setType('img')
                ->setContext('restaurant_picture')
                ->setUpdatedAt(new \DateTime())
            ;
            $media->setRestaurant($restaurant);
            $em->persist($media);
        }

        $restaurant->setIsActivated(false);
        $em->persist($restaurant);
        $em->flush();
    }

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

my FormType(called RestaurantType) where I added a field for file upload (when I set up multiple to false it actually works for only one picture)

$builder
        ->add('picture', FileType::class, array(
            'label'                 => 'Photos du restaurant',
            'multiple'              => true,
            'required'              => false,
            'mapped'                => false,
            'attr'                  => array(
                'accept'                => '.jpg,.jpeg,.png'),
        ))

The service to uploads file

    class FileUploader
{
    /**
     * @param UploadedFile $file
     * @param $targetDir
     * @return string
     */
    public function upload(UploadedFile $file, $targetDir)
    {
        $fileName = md5(uniqid()).'.'.$file->guessExtension();
        $file->move($targetDir, $fileName);
        return $fileName;
    }
}

the queryBuilder in the MediaRepository

public function findPictureByRestaurant(Restaurant $restaurant)
{
    return $this->createQueryBuilder('m')
        ->select('m')
        ->where('m.restaurant = :restaurant')
        ->setParameter('restaurant', $restaurant)
        ->andWhere('m.context = :restaurant_picture')
        ->setParameter('restaurant_picture', 'restaurant_picture')
        ->getQuery()
        ->getOneOrNullResult();
}

in my show.html.twig where you can see the picture

{% if restaurant.medias != null and restaurant.medias.count > 0 and restaurant.medias[0].name != null %}
        <img src="/uploads/restaurants/{{ restaurant.medias[0].name }}">
{% endif %}

my config.yml where the files are uploaded

parameters:
    locale: fr
        uploaded_restaurants: "%kernel.root_dir%/../web/uploads/restaurants"

And the entity Restaurant which is pretty long (sorry)

    /**
 * Restaurant
 *
 * @ORM\Table(name="restaurant")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\RestaurantRepository")
 */
class Restaurant
{
    /**
     * @var FoodType
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\FoodType", inversedBy="restaurants")
     * @ORM\JoinColumn(name="food_type_id", referencedColumnName="id")
     */
    private $foodType;

    /**
     * @var City
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\City", inversedBy="restaurants")
     * @ORM\JoinColumn(name="city_id", referencedColumnName="id")
     */
    private $city;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Media", mappedBy="restaurant")
     */
    private $medias;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Privatisation", mappedBy="restaurant")
     */
    private $privatisations;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Retrocession", mappedBy="restaurant")
     */
    private $retrocessions;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\OpenedSlot", mappedBy="restaurant")
     */
    private $openedSlots;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\ExceptionSlot", mappedBy="restaurant")
     */
    private $exceptionSlots;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Slot", mappedBy="restaurant")
     */
    private $slots;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Chef", mappedBy="restaurant")
     */
    private $chefs;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->medias = new ArrayCollection();
        $this->privatisations = new ArrayCollection();
        $this->retrocessions = new ArrayCollection();
        $this->openedSlots = new ArrayCollection();
        $this->exceptionSlots = new ArrayCollection();
        $this->slots = new ArrayCollection();
        $this->chefs = new ArrayCollection();
    }

    /**
     * @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=120, unique=true)
     * @Assert\Length(
     *     max = 120,
     *     maxMessage = "Ce champ ne peut pas dépasser {{ limit }} caractères."
     *     )
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="slug", type="string", length=255, unique=true)
     * @Gedmo\Slug(fields={"name"})
     * @Assert\Length(
     *    max = 255,
     *    maxMessage = "Ce champ ne peut pas dépasser {{ limit }} caractères."
     *    )
     */
    private $slug;

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

    /**
     * @var string
     *
     * @ORM\Column(name="webUrl", type="string", length=255, nullable=true)
     * @Assert\Length(
     *    max = 255,
     *    maxMessage = "Ce champ ne peut pas dépasser {{ limit }} caractères."
     *    )
     */
    private $webUrl;

    /**
     * @var string
     *
     * @ORM\Column(name="tripAdvisorUrl", type="string", length=255, nullable=true)
     * @Assert\Length(
     *    max = 255,
     *    maxMessage = "Ce champ ne peut pas dépasser {{ limit }} caractères."
     *    )
     */
    private $tripAdvisorUrl;

    /**
     * @var string
     *
     * @ORM\Column(name="facebookUrl", type="string", length=255, nullable=true)
     * @Assert\Length(
     *    max = 255,
     *    maxMessage = "Ce champ ne peut pas dépasser {{ limit }} caractères."
     *    )
     */
    private $facebookUrl;

    /**
     * @var string
     *
     * @ORM\Column(name="twitterUrl", type="string", length=255, nullable=true)
     * @Assert\Length(
     *    max = 255,
     *    maxMessage = "Ce champ ne peut pas dépasser {{ limit }} caractères."
     *    )
     */
    private $twitterUrl;

    /**
     * @var string
     *
     * @ORM\Column(name="instagramUrl", type="string", length=255, nullable=true)
     * @Assert\Length(
     *    max = 255,
     *    maxMessage = "Ce champ ne peut pas dépasser {{ limit }} caractères."
     *    )
     */
    private $instagramUrl;

    /**
     * @var string
     *
     * @ORM\Column(name="phone", type="string", length=20)
     * @Assert\Regex(
     *     pattern="#^0[1-9]([-. ]?[0-9]{2}){4}$#",
     *     match=true,
     *     message="Numéro de téléphone invalide."
     *     )
     */
    private $phone;

    /**
     * @var string
     *
     * @ORM\Column(name="phone2", type="string", length=20, nullable=true)
     * @Assert\Regex(
     *     pattern="#^0[1-9]([-. ]?[0-9]{2}){4}$#",
     *     match=true,
     *     message="Numéro de téléphone invalide."
     *     )
     */
    private $phone2;

    /**
     * @var string
     *
     * @ORM\Column(name="email", type="string", length=255)
     * @Assert\Length(
     *    max = 255,
     *    maxMessage = "Ce champ ne peut pas dépasser {{ limit }} caractères."
     *    )
     */
    private $email;

    /**
     * @var float
     *
     * @ORM\Column(name="latitude", type="float")
     * @Assert\Regex(
     *     pattern="/^-?(?:\d+|\d*\.\d+)$/",
     *     match=true,
     *     )
     */
    private $latitude;

    /**
     * @var float
     *
     * @ORM\Column(name="longitude", type="float")
     * @Assert\Regex(
     *     pattern="/^-?(?:\d+|\d*\.\d+)$/",
     *     match=true,
     *     )
     */
    private $longitude;

    /**
     * @var int
     *
     * @ORM\Column(name="stars", type="integer", nullable=true)
     * @Assert\Regex(
     *     pattern="/^[0-9]+$/",
     *     match=true,
     *     message="Ceci n'est pas un chiffre."
     *     )
     */
    private $stars;

    /**
     * @var int
     *
     * @ORM\Column(name="seatNumber", type="integer", nullable=true)
     * @Assert\Regex(
     *     pattern="/^[0-9]+$/",
     *     match=true,
     *     )
     */
    private $seatNumber;

    /**
     * @var float
     *
     * @ORM\Column(name="minPrice", type="float", nullable=true)
     * @Assert\Regex(
     *     pattern="/^-?(?:\d+|\d*\.\d+)$/",
     *     match=true,
     *     )
     */
    private $minPrice;

    /**
     * @var float
     *
     * @ORM\Column(name="maxPrice", type="float", nullable=true)
     * @Assert\Regex(
     *     pattern="/^-?(?:\d+|\d*\.\d+)$/",
     *     match=true,
     *     )
     */
    private $maxPrice;

    /**
     * @var string
     *
     * @ORM\Column(name="address", type="string", length=255)
     * @Assert\Length(
     *    max = 255,
     *    maxMessage = "Ce champ ne peut pas dépasser {{ limit }} caractères."
     *    )
     */
    private $address;

    /**
     * @var bool
     *
     * @ORM\Column(name="is_activated", type="boolean")
     */
    private $isActivated = true;

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

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

        return $this;
    }

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

    /**
     * Set slug
     *
     * @param string $slug
     *
     * @return Restaurant
     */
    public function setSlug($slug)
    {
        $this->slug = $slug;

        return $this;
    }

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

    /**
     * Set description
     *
     * @param string $description
     *
     * @return Restaurant
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

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

    /**
     * Set webUrl
     *
     * @param string $webUrl
     *
     * @return Restaurant
     */
    public function setWebUrl($webUrl)
    {
        $this->webUrl = $webUrl;

        return $this;
    }

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

    /**
     * Set tripAdvisorUrl
     *
     * @param string $tripAdvisorUrl
     *
     * @return Restaurant
     */
    public function setTripAdvisorUrl($tripAdvisorUrl)
    {
        $this->tripAdvisorUrl = $tripAdvisorUrl;

        return $this;
    }

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

    /**
     * Set facebookUrl
     *
     * @param string $facebookUrl
     *
     * @return Restaurant
     */
    public function setFacebookUrl($facebookUrl)
    {
        $this->facebookUrl = $facebookUrl;

        return $this;
    }

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

    /**
     * Set twitterUrl
     *
     * @param string $twitterUrl
     *
     * @return Restaurant
     */
    public function setTwitterUrl($twitterUrl)
    {
        $this->twitterUrl = $twitterUrl;

        return $this;
    }

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

    /**
     * Set instagramUrl
     *
     * @param string $instagramUrl
     *
     * @return Restaurant
     */
    public function setInstagramUrl($instagramUrl)
    {
        $this->instagramUrl = $instagramUrl;

        return $this;
    }

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

    /**
     * Set phone
     *
     * @param string $phone
     *
     * @return Restaurant
     */
    public function setPhone($phone)
    {
        $this->phone = $phone;

        return $this;
    }

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

    /**
     * Set phone2
     *
     * @param string $phone2
     *
     * @return Restaurant
     */
    public function setPhone2($phone2)
    {
        $this->phone2 = $phone2;

        return $this;
    }

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

    /**
     * Set email
     *
     * @param string $email
     *
     * @return Restaurant
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

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

    /**
     * Set latitude
     *
     * @param float $latitude
     *
     * @return Restaurant
     */
    public function setLatitude($latitude)
    {
        $this->latitude = $latitude;

        return $this;
    }

    /**
     * Get latitude
     *
     * @return float
     */
    public function getLatitude()
    {
        return $this->latitude;
    }

    /**
     * Set longitude
     *
     * @param float $longitude
     *
     * @return Restaurant
     */
    public function setLongitude($longitude)
    {
        $this->longitude = $longitude;

        return $this;
    }

    /**
     * Get longitude
     *
     * @return float
     */
    public function getLongitude()
    {
        return $this->longitude;
    }

    /**
     * Set stars
     *
     * @param integer $stars
     *
     * @return Restaurant
     */
    public function setStars($stars)
    {
        $this->stars = $stars;

        return $this;
    }

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

    /**
     * Set seatNumber
     *
     * @param integer $seatNumber
     *
     * @return Restaurant
     */
    public function setSeatNumber($seatNumber)
    {
        $this->seatNumber = $seatNumber;

        return $this;
    }

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

    /**
     * Set minPrice
     *
     * @param float $minPrice
     *
     * @return Restaurant
     */
    public function setMinPrice($minPrice)
    {
        $this->minPrice = $minPrice;

        return $this;
    }

    /**
     * Get minPrice
     *
     * @return float
     */
    public function getMinPrice()
    {
        return $this->minPrice;
    }

    /**
     * Set maxPrice
     *
     * @param float $maxPrice
     *
     * @return Restaurant
     */
    public function setMaxPrice($maxPrice)
    {
        $this->maxPrice = $maxPrice;

        return $this;
    }

    /**
     * Get maxPrice
     *
     * @return float
     */
    public function getMaxPrice()
    {
        return $this->maxPrice;
    }

    /**
     * Set address
     *
     * @param string $address
     *
     * @return Restaurant
     */
    public function setAddress($address)
    {
        $this->address = $address;

        return $this;
    }

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

    /**
     * Add media
     *
     * @param Media $media
     *
     * @return Restaurant
     */
    public function addMedia(Media $media)
    {
        $this->medias[] = $media;

        return $this;
    }

    /**
     * Remove media
     *
     * @param Media $media
     */
    public function removeMedia(Media $media)
    {
        $this->medias->removeElement($media);
    }

    /**
     * Get medias
     *
     * @return ArrayCollection
     */
    public function getMedias()
    {
        return $this->medias;
    }

    /**
     * Set foodType
     *
     * @param FoodType $foodType
     *
     * @return Restaurant
     */
    public function setFoodType(FoodType $foodType = null)
    {
        $this->foodType = $foodType;

        return $this;
    }

    /**
     * Get foodType
     *
     * @return FoodType
     */
    public function getFoodType()
    {
        return $this->foodType;
    }

    /**
     * Add privatisation
     *
     * @param Privatisation $privatisation
     *
     * @return Restaurant
     */
    public function addPrivatisation(Privatisation $privatisation)
    {
        $this->privatisations[] = $privatisation;

        return $this;
    }

    /**
     * Remove privatisation
     *
     * @param Privatisation $privatisation
     */
    public function removePrivatisation(Privatisation $privatisation)
    {
        $this->privatisations->removeElement($privatisation);
    }

    /**
     * Get privatisations
     *
     * @return ArrayCollection
     */
    public function getPrivatisations()
    {
        return $this->privatisations;
    }

    /**
     * Add retrocession
     *
     * @param Retrocession $retrocession
     *
     * @return Restaurant
     */
    public function addRetrocession(Retrocession $retrocession)
    {
        $this->retrocessions[] = $retrocession;

        return $this;
    }

    /**
     * Remove retrocession
     *
     * @param Retrocession $retrocession
     */
    public function removeRetrocession(Retrocession $retrocession)
    {
        $this->retrocessions->removeElement($retrocession);
    }

    /**
     * Get retrocessions
     *
     * @return ArrayCollection
     */
    public function getRetrocessions()
    {
        return $this->retrocessions;
    }

    /**
     * Add openedSlot
     *
     * @param OpenedSlot $openedSlot
     *
     * @return Restaurant
     */
    public function addOpenedSlot(OpenedSlot $openedSlot)
    {
        $this->openedSlots[] = $openedSlot;

        return $this;
    }

    /**
     * Remove openedSlot
     *
     * @param OpenedSlot $openedSlot
     */
    public function removeOpenedSlot(OpenedSlot $openedSlot)
    {
        $this->openedSlots->removeElement($openedSlot);
    }

    /**
     * Get openedSlots
     *
     * @return ArrayCollection
     */
    public function getOpenedSlots()
    {
        return $this->openedSlots;
    }

    /**
     * Add exceptionSlot
     *
     * @param ExceptionSlot $exceptionSlot
     *
     * @return Restaurant
     */
    public function addExceptionSlot(ExceptionSlot $exceptionSlot)
    {
        $this->exceptionSlots[] = $exceptionSlot;

        return $this;
    }

    /**
     * Remove exceptionSlot
     *
     * @param ExceptionSlot $exceptionSlot
     */
    public function removeExceptionSlot(ExceptionSlot $exceptionSlot)
    {
        $this->exceptionSlots->removeElement($exceptionSlot);
    }

    /**
     * Get exceptionSlots
     *
     * @return ArrayCollection
     */
    public function getExceptionSlots()
    {
        return $this->exceptionSlots;
    }

    /**
     * Add slot
     *
     * @param Slot $slot
     *
     * @return Restaurant
     */
    public function addSlot(Slot $slot)
    {
        $this->slots[] = $slot;

        return $this;
    }

    /**
     * Remove slot
     *
     * @param Slot $slot
     */
    public function removeSlot(Slot $slot)
    {
        $this->slots->removeElement($slot);
    }

    /**
     * Get slots
     *
     * @return ArrayCollection
     */
    public function getSlots()
    {
        return $this->slots;
    }

    /**
     * Add chef
     *
     * @param Chef $chef
     *
     * @return Restaurant
     */
    public function addChef(Chef $chef)
    {
        $this->chefs[] = $chef;

        return $this;
    }

    /**
     * Remove chef
     *
     * @param Chef $chef
     */
    public function removeChef(Chef $chef)
    {
        $this->chefs->removeElement($chef);
    }

    /**
     * Get chefs
     *
     * @return ArrayCollection
     */
    public function getChefs()
    {
        return $this->chefs;
    }

    /**
     * Set city
     *
     * @param City $city
     *
     * @return Restaurant
     */
    public function setCity(City $city = null)
    {
        $this->city = $city;

        return $this;
    }

    /**
     * Get city
     *
     * @return City
     */
    public function getCity()
    {
        return $this->city;
    }

    /**
     * @return bool
     */
    public function getIsActivated()
    {
        return $this->isActivated;
    }

    /**
     * @param bool $isActivated
     */
    public function setIsActivated($isActivated)
    {
        $this->isActivated = $isActivated;
    }
}

and the error that comes up when I upload a picture and click on submit button

enter image description here

To sum up it up all, this code works for only one picture when I set up multiple to false in my FormType. But then I am stuck for the multiple file upload and I can't get to find a way around that. Does someone know how to handle it with the code I given you?

Thank you

2
  • Give a read to this article Commented Mar 9, 2017 at 18:12
  • Thank you @DanCostinel! much appreciated for this! :) Commented Mar 9, 2017 at 20:31

2 Answers 2

1

Because your file definition accept multiple uploads, you need to modify upload part of your controller:

// file upload
if ($request->files->get('restaurant')['picture'] != null) {
    $files = $request->files->get('restaurant')['picture'];
    foreach ($files as $file) {
        $targetDir = $this->getParameter('uploaded_restaurants');
        $filename = $this->get('app.uploader')->upload($file, $targetDir);
        $mediaRestaurant = null;
        if ($restaurant->getId() != null) {
            $mediaRestaurant = $this->getDoctrine()->getRepository('AppBundle:Media')->findPictureByRestaurant($restaurant);
        }
        if ($mediaRestaurant) {
            $media = $mediaRestaurant;
            $fs = new Filesystem();
            try {
                $fs->remove($this->get('kernel')->getRootDir().'/../web/uploads/restaurants/'.$media->getName());
            } catch (IOException $e) {
                echo "error";
            }
        } else {
            $media = new Media();
            $media->setCreatedAt(new \DateTime());
        }
        $originalName = $file->getClientOriginalName();
        $media->setName($filename)
            ->setOriginalName($originalName)
            ->setType('img')
            ->setContext('restaurant_picture')
            ->setUpdatedAt(new \DateTime())
            ;
        $media->setRestaurant($restaurant);
        $em->persist($media);
    }
}

Notify that I've taken all files from form uploaded data first, and run your code in a foreach loop.

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

3 Comments

Thank you for your answer, I did what you have done, but I get this error when I upload more than one picture SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'the_name_of_the_form' for key 'UNIQ_EB95123F5E237E06'
Show us the entity class then (please update first post).
I edited the post with the entity Restaurant (f that was what you expected)
1

You need to handle an array in your upload method, as itll get that from the form, rather than an individual UploadedFile object.

/**
 * @param UploadedFile $file
 * @param $targetDir
 * @return array
 */
public function upload($files, $targetDir)
{
    if(!is_array($files)) {
         $files = (array) $files; // cast to array in case of a form that isn't multiple.
    }
    $filenames = [];
    foreach($files as $file) {
         $filenames[] = md5(uniqid()).'.'.$file->guessExtension();
         $file->move($targetDir, $fileName);
    }

    return $filenames;
}

youll need to twiddle whatever is getting the return filename variable, as it'll now be an array.

The other way, which in my opinion is a better UX, is to use a CollectionType and render a file input box per file. Heres a quick example.

    $builder->add('file_uploads', CollectionType::class, [
        'entry_type'    => FileType::class,
        'entry_options' => [
            'label'        => 'Photos du restaurant',
            'multiple'     => true,
            'required'     => false,
            'mapped'       => false,
            'attr'         => [
                'accept' => '.jpg,.jpeg,.png',
            ],
            'allow_add'    => true,
            'allow_delete' => true,
        ],
        'prototype'     => true,
    ]);

Youll then need to handle the resulting ArrayCollection in your upload handler. But this gives a much nicer interface for the user.

Ive not tested this snippet, so you might have to debug or adapt it to fit with what you're doing.

2 Comments

thank you for your answer, i actually used a collection type in one of my attempt, I created a MediaType form and added in my RestaurantType with the CollectionType property. But couldn't make it done as my file upoloader wasn't working properly multiple_files I will try your method as well
I used your first method (where you change the UploadedFile) and I get this error when I create a new restaurant Warning: strrpos() expects parameter 1 to be string, array given

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.