Symfony Mapping not found for field"imageNameVehicle"

63 Views Asked by At

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.

1

There are 1 best solutions below

0
exepti0n On

According to the documentation you should map your form field to the File property, not the property that will hold the filename:

In your case it should be:

- ->add('imageNameVehicle', VichImageType::class, [
+ ->add('imageFile', VichImageType::class, [
    'label' => 'Image',
    'required' => false,
    'attr' => ['class' => 'form-control'],
])