I have a small problem, I'm stuck, would it be possible to help me?
enter image description here enter image description here
vich_uploader.yaml
vich_uploader:
db_driver: orm
metadata:
type: attribute
mappings:
ServiceImage:
uri_prefix: /assets/img_uploads/Services
upload_destination: "%kernel.project_dir%/public/assets/img_uploads/Services"
namer: Vich\UploaderBundle\Naming\SmartUniqueNamer
VehicleImage:
uri_prefix: /assets/img_uploads/Vehicles
upload_destination: "%kernel.project_dir%/public/assets/img_uploads/Vehicles"
namer: Vich\UploaderBundle\Naming\SmartUniqueNamer
file Entity
<?php
namespace App\Entity;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\VparServiceRepository;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Vich\UploaderBundle\Mapping\Annotation\Uploadable;
#[ORM\Entity(repositoryClass: VparServiceRepository::class)]
#[Uploadable]
class VparService
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $updatedAt = null;
#[ORM\Column(length: 255)]
private ?string $title = null;
#[ORM\Column(type: Types::TEXT)]
private ?string $text = null;
#[Vich\UploadableField(mapping: 'ServiceImage', fileNameProperty: 'imageNameVehicle')]
private ?File $imageFile = null;
#[ORM\Column(nullable: true)]
private ?string $imageNameVehicle = null;
public function getId(): ?int
{
return $this->id;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(\DateTimeInterface $updatedAt): static
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getText(): ?string
{
return $this->text;
}
public function setText(string $text): static
{
$this->text = $text;
return $this;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): static
{
$this->title = $title;
return $this;
}
public function setImageFile(?File $imageFile = null): void
{
$this->imageFile = $imageFile;
if (null !== $imageFile) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTimeImmutable();
}
}
public function getImageFile(): ?File
{
return $this->imageFile;
}
public function setImageNameVehicle(?string $imageNameVehicle): void
{
$this->imageNameVehicle = $imageNameVehicle;
}
public function getImageNameVehicle(): ?string
{
return $this->imageNameVehicle;
}
}
fileformType
<?php
namespace App\Form;
use App\Entity\VparService;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Vich\UploaderBundle\Form\Type\VichImageType;
class ServicesType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('title', TextType::class, [
'label' => 'Nom du service',
'attr' => ['class' => 'form-control'],
])
->add('text', TextareaType::class, [
'label' => 'Description du service',
'attr' => ['class' => 'form-control'],
])
->add('imageNameVehicle', VichImageType::class, [
'label' => 'Image',
'required' => false,
'attr' => ['class' => 'form-control'],
])
->add('submit', SubmitType::class, [
'label' => 'Enregistrer',
'attr' => ['class' => 'btn btn-primary'],
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => VparService::class,
]);
}
}
controller
<?php
namespace App\Controller;
use App\Form\ServicesType;
use Doctrine\ORM\EntityManagerInterface;
use App\Repository\VparServiceRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class ServicesController extends AbstractController
{
#[IsGranted('ROLE_ADMIN')]
#[Route('/back/gestion-des-services', name: 'app_services')]
public function index(VparServiceRepository $services): Response
{
return $this->render('pages/services/gServices.html.twig', [
'title_page' => 'Gestion des services | V.Parrot',
'nav_item1' => 'Retour vers le site',
'nav_item2' => 'Gestion des ventes',
'nav_item3' => 'Gestion des services',
'nav_item4' => 'Gestion des horaires',
'nav_item5' => 'Gestion des employés',
'nav_item6' => 'Gestion des avis clients',
'nav_item7' => 'Déconnexion',
'h1_index' => 'Gestion des Services',
'h2_index' => 'Service actuellement proposés',
'add_btn' => 'Ajouter un nouveau service',
'th_name' => 'Nom du service',
'th_text' => 'Description du service',
'th_img' => 'Image du service',
'td_modify' => 'Modifier',
'td_delete' => 'Supprimer',
'services' => $services->findAll(),
]);
}
#[IsGranted('ROLE_ADMIN')]
#[Route('/back/gestion-des-services/edition/{id}', name: 'app_gestion_services_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, VparServiceRepository $services, EntityManagerInterface $em, int $id): Response
{
$service = $services->find($id);
$form = $this->createForm(ServicesType::class, $service);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$service->setUpdatedAt(new \DateTime());
$em->flush();
$this->addFlash('success', 'Le service a bien été modifié.');
return $this->redirectToRoute('app_services');
}
return $this->render('pages/services/gServicesEdit.html.twig', [
'title_page' => 'modification d\'un employé | V.Parrot',
'nav_item1' => 'Retour vers le site',
'nav_item2' => 'Gestion des ventes',
'nav_item3' => 'Gestion des services',
'nav_item4' => 'Gestion des horaires',
'nav_item5' => 'Gestion des employés',
'nav_item6' => 'Gestion des avis clients',
'nav_item7' => 'Déconnexion',
'h1_edit' => 'Gestion des Services',
'h2_edit' => 'Modifier un service',
'form' => $form->createView(),
]);
}
}
Filetwig
{% extends "base.html.twig" %}
{% block title %}{{ title_page }}{% endblock %}
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" href="{{ asset('assets/styles/general_backoffice.css') }}">
<link rel="stylesheet" href="{{ asset('assets/styles/general_form_backoffice.css') }}">
<link rel="stylesheet" href="{{ asset('assets/styles/add_modify_form_backoffice.css') }}">
<link rel="stylesheet" href="{{ asset('assets/styles/button_backoffice.css') }}">
{% endblock %}
{% block header %}
{{ include("partials/_header.html.twig") }}
{{ include("partials/_nav_back.html.twig") }}
{% endblock %}
{% block body %}
<div class="container">
<h1>{{ h1_edit }}</h1>
<h2>{{ h2_edit }}</h2>
{{ form_start(form) }}
{{ form_row(form.title) }}
{{ form_row(form.text) }}
{{ form_row(form.imageNameVehicle) }}
<div class="addBtn">
{{ form_row(form.submit) }}
</div>
{{ form_end(form) }}
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const downloadLinks = document.querySelectorAll('a[download]');
downloadLinks.forEach(link => {
if (link.textContent.toLowerCase().trim() === 'download') {
link.textContent = 'Télécharger';
}
});
const deleteLabels = document.querySelectorAll('label[for$="_delete"]');
deleteLabels.forEach(label => {
if (label.textContent.toLowerCase().trim() === 'delete?') {
label.textContent = 'Supprimer';
}
});
});
</script>
{% endblock %}
I admit, I'm just starting out and I'm a little lost. Could someone explain it to me and help me.
Would it be possible to debug this? And to explain to me where the problem comes from, to understand my error so as not to reproduce it again. Thank you for your support.
According to the documentation you should map your form field to the
Fileproperty, not the property that will hold the filename:In your case it should be: