I'm new to Symfony and I'm struggling a lot trying to find a way to upload multiple files. I'm trying to build an app have apartment and each apartment can have multiple images.
Appartment(OneToMany) - Image(ManyToOne)
so I created 2 entities and added a field in my AppartmentTypeForm called 'image' which is a CollectionType::class of 'name' in my ImageTypeForm which is a FileType::class
I added some js to be able to add multiple input files by clicking a button
everything works until I submit the form,I cannot get the image names if I add 3 images and I try to
$photo = $form->get('image')->getData();
I will see my 3 arrays only the id of my apartment is set no name no file nothing.
I'm probably doing something wrong, but I can't see where.
Controller, as you will see iI tried to foreach my image data, but I can only get 1 of the file name and even when I try to flush() everything Symfony returns an error because it tries to set my database column 'name' as null...,
#[Route('/create_product', name: 'create_product', methods: ['GET', 'POST'])]
public function createProduct(EntityManagerInterface $em, Request $request, SluggerInterface $slugger): Response
{
$image = new Image;
$product = new Appartment;
$form = $this->createForm(AppartmentTypeFormType::class, $product);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$product->setCreatedAt(new DateTime());
$product->setUpdatedAt(new DateTime());
$product->setCountry($form->get('country')->getData());
$image->setCreatedAt(new DateTime());
$image->setUpdatedAt(new DateTime());
foreach ($form->get('image') as $formChild) {
$uploadedImages = $formChild->get('name')->getData();
$uploadedImage = $uploadedImages[0];
$newFileName = $this->handleFile($slugger, $uploadedImage);
$image->setName($newFileName);
}
}
$em->persist($product);
$em->persist($image);
$em->flush();
$this->addFlash('success', "votre produit a bien était ajouté");
return $this->render('admin/create_product.html.twig', [
'form' => $form->createView(),
]);
}
public function handleFile($slugger, $image)
{
$extension = '.' . $image->guessExtension();
$originalFileName = $slugger->slug($image->getClientOriginalName());
$newFileName = $originalFileName . uniqid() . $extension;
try {
$image->move($this->getParameter('uploads_directory'), $newFileName);
} catch (FileException $fe) {
//throw $th;
}
return $newFileName;
}
Appartment Entity (OneToMany)
#[ORM\ManyToOne(inversedBy: 'appartments')]
#[ORM\JoinColumn(nullable: false)]
private ?Country $country = null;
#[ORM\OneToMany(mappedBy: 'image', targetEntity: Image::class, cascade:["persist"])]
private Collection $image;
public function __construct()
{
$this->image = new ArrayCollection();
}
/**
* @return Collection<int, Image>
*/
public function getImage(): Collection
{
return $this->image;
}
public function addImage(Image $image): self
{
if (!$this->image->contains($image)) {
$this->image->add($image);
$image->setImage($this);
}
return $this;
}
public function removeImage(Image $image): self
{
if ($this->image->removeElement($image)) {
// set the owning side to null (unless already changed)
if ($image->getImage() === $this) {
$image->setImage(null);
}
}
return $this;
}
Image Entity (ManyToOne)
#[ORM\Entity(repositoryClass: ImageRepository::class)]
class Image
{
use TimestampableEntity;
use SoftDeleteableEntity;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\ManyToOne(inversedBy: 'image')]
private ?Appartment $image = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
public function getId(): ?int
{
return $this->id;
}
public function getImage(): ?Appartment
{
return $this->image;
}
public function setImage(?Appartment $image): self
{
$this->image = $image;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
AppartmentTypeForm
class AppartmentTypeFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('title')
->add('description')
->add('beds')
->add('price')
->add('city')
->add('address')
->add('postal_code')
->add('country',EntityType::class, [
'class' => Country::class,
'choice_label' => 'name'
])
->add('image', CollectionType::class, [
'entry_type' => ImageTypeFormType::class,
'constraints' => [
new Valid()
],
'entry_options' => ['label' => false],
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
])
->add('submit', SubmitType::class, [
'label' => 'envoyer',
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Appartment::class,
'allow_file_upload' => true
]);
}
}
ImageTypeForm
class ImageTypeFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', FileType::class, [
'label' => false,
'constraints' => [
new All([
new File(
[ "mimeTypes" => ["image/png",
"image/jpg",
"image/jpeg",
"image/gif"]]
)]),
new Valid(),
],
'multiple' => true,
'mapped' => false,
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Image::class,
'allow_file_upload' => true
]);
}
}
this is what I get when I
$image = form->get('image')->getData();
dd($image) return me this
AdminController.php on line 50:
Doctrine\Common\Collections\ArrayCollection {#1191 ▼
-elements: array:3 [▼
0 => App\Entity\Image {#1343 ▼
-id: null
-image: App\Entity\Appartment {#526 ▶}
-name: null
#createdAt: null
#updatedAt: null
#deletedAt: null
}
1 => App\Entity\Image {#1247 ▼
-id: null
-image: App\Entity\Appartment {#526}
-name: null
#createdAt: null
#updatedAt: null
#deletedAt: null
}
2 => App\Entity\Image {#1257 ▼
-id: null
-image: App\Entity\Appartment {#526}
-name: null
#createdAt: null
#updatedAt: null
#deletedAt: null
}
]
}
and this is what I get when I do it for files
$photo = $request->files;
dd($photo); return me this
AdminController.php on line 50:
Symfony\Component\HttpFoundation\FileBag {#55 ▼
#parameters: array:1 [▼
"appartment_type_form" => array:1 [▼
"image" => array:3 [▼
0 => array:1 [▼
"name" => array:1 [▼
0 => Symfony\Component\HttpFoundation\File\UploadedFile {#60 ▼
-test: false
-originalName: "FaYS3XxWQAAesmS.jpg"
-mimeType: "image/jpeg"
-error: 0
path: "C:\xampp\tmp"
filename: "php6EE1.tmp"
basename: "php6EE1.tmp"
pathname: "C:\xampp\tmp\php6EE1.tmp"
extension: "tmp"
realPath: "C:\xampp\tmp\php6EE1.tmp"
aTime: 2022-09-18 08:43:33
mTime: 2022-09-18 08:43:32
cTime: 2022-09-18 08:43:32
inode: 2251799814701650
size: 129133
perms: 0100666
owner: 0
group: 0
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
linkTarget: "C:\xampp\tmp\php6EE1.tmp"
}
]
]
1 => array:1 [▼
"name" => array:1 [▼
0 => Symfony\Component\HttpFoundation\File\UploadedFile {#43 ▼
-test: false
-originalName: "FUR6LQ3X0AQxOIW.jpg"
-mimeType: "image/jpeg"
-error: 0
path: "C:\xampp\tmp"
filename: "php6EE2.tmp"
basename: "php6EE2.tmp"
pathname: "C:\xampp\tmp\php6EE2.tmp"
extension: "tmp"
realPath: "C:\xampp\tmp\php6EE2.tmp"
aTime: 2022-09-18 08:43:33
mTime: 2022-09-18 08:43:32
cTime: 2022-09-18 08:43:32
inode: 1970324837991018
size: 69872
perms: 0100666
owner: 0
group: 0
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
linkTarget: "C:\xampp\tmp\php6EE2.tmp"
}
]
]
2 => array:1 [▼
"name" => array:1 [▼
0 => Symfony\Component\HttpFoundation\File\UploadedFile {#42 ▼
-test: false
-originalName: "8fecc63aa4d247d6895b0de17e38b858.jpg"
-mimeType: "image/jpeg"
-error: 0
path: "C:\xampp\tmp"
filename: "php6EE3.tmp"
basename: "php6EE3.tmp"
pathname: "C:\xampp\tmp\php6EE3.tmp"
extension: "tmp"
realPath: "C:\xampp\tmp\php6EE3.tmp"
aTime: 2022-09-18 08:43:33
mTime: 2022-09-18 08:43:32
cTime: 2022-09-18 08:43:32
inode: 1688849861280373
size: 565083
perms: 0100666
owner: 0
group: 0
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
linkTarget: "C:\xampp\tmp\php6EE3.tmp"
}
]
]
]
]
]
}
I'm sorry it's a bit long, but I tried to search everywhere couldn't find a response
thank you.
So little Edit:
When I submit my file my images are renamed and uploaded in my uploads_directory I don't know how or why. I changed nothing,
but still how can I get my database column name to be equal to my file name.
Second Edit:
I managed to upload 1 image in my db by changing
$image->setName($newFileName);
$em->persist($image)
by this:
$em->persist($image->setName($newFileName));
but I still can't get all my images to get in database.
CodePudding user response:
Move $image = new Image;
and $em->persist($image);
to the foreach section
...
foreach ($form->get('image') as $formChild) {
$image = new Image; // added
$image->setCreatedAt(new DateTime()); // added
$image->setUpdatedAt(new DateTime()); // added
$uploadedImages = $formChild->get('name')->getData();
$uploadedImage = $uploadedImages[0];
$newFileName = $this->handleFile($slugger, $uploadedImage);
$image->setName($newFileName);
$em->persist($image); // added
}
...