The rendering of a template "Field "nom" has already been rendered, save the result of previous render call to a variable and output that instead

  macros, php, symfony4

ManyTOMany Relation , using macros Symfony 5.
for my project:
I need to add a Catalog and have a possibility to add several images in the same form using "macros",
The problem is that I have this error and I searched a lot without any results

Catalogue Twig :

{% macro mediaForm(med) %}
<div class=" formitem">
    <div class="form-row mb-4">
        <div class="form-group col-md-6">
            <label for="">Nom du média :</label>
            {{ form_widget(med.nom) }}
        </div>
        <div class="form-group col-md-6">
            <label for="">Ajout média : </label>
            {{ form_widget(med.chemin) }}
        </div>
    </div>
    <div class="form-row mb-4">
        <div class="form-group col-md-6">
            <label for="">Description :</label>
            {{ form_widget(med.description) }}
        </div>
        {# <div class="form-group col-md-6">
            <label for="">Les catalogues : </label>
            {{ form_widget(row.catalogues) }}
        </div> #}
    </div>


    <div class="col-lg-12">
               <button  class=" contratdiv btn btn-primary px-5 float-right">
                            Annuler média
                      </button>
    </div>  </br> 
</div>

{% endmacro mediaForm %}



{{ form_start(form) }}

    <div class="form-row mb-4">
        <div class="form-group col-md-6">
            <label for="">Nom du Catalogue :</label>
            {{ form_widget(form.nom) }}
        </div>
        <div class="form-group col-md-6">
            <label for="">Photo Miniature :</label>
            {{ form_widget(form.miniature) }}
        </div>
    </div>
    <div class="form-row mb-4">
        <div class="form-group col-md-6">
            <label for="">média :</label>
            {{ form_widget(form.medias) }}
        </div>
        <div class="form-group col-md-6">
        </div>
       
    </div>
    <div class="" id="catalogue_form" 
                    data-prototype=" {{_self.mediaForm(form.medias.vars.prototype)|e('html_attr')}}"
                    data-index="{{ form.medias|length }}" >
                    <div class=" form-group col-lg-12">
                        {% for med in form.medias %}
                                {{ _self.mediaForm(med) }}      
                        {% endfor %}
                            
                                <button  class=" btn btn-primary px-5">
                                        Ajouter un média
                                </button> 
                            </div>
                    </div>
        </div>
    

    <button class="btn btn-primary float-right px-5">{{ button_label|default('Ajouter') }}</button>
{{ form_end(form, {'render_rest': false}) }} 

CatalogueController :

<?php

namespace AppController;

use AppEntityMedia;
use AppEntityCatalogue;
use AppFormCatalogueType;
use AppRepositoryCatalogueRepository;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentRoutingAnnotationRoute;
use SymfonyComponentHttpFoundationJsonResponse;
use SymfonyBundleFrameworkBundleControllerAbstractController;

#[Route('/catalogue')]
class CatalogueController extends AbstractController
{
    #[Route('/', name: 'catalogue_index', methods: ['GET'])]
    public function index(CatalogueRepository $catalogueRepository): Response
    {
        return $this->render('catalogue/index.html.twig', [
            'catalogues' => $catalogueRepository->findAll(),
        ]);
    }

    #[Route('/new', name: 'catalogue_new', methods: ['GET', 'POST'])]
    public function new(Request $request): Response
    {
        $catalogue = new Catalogue();
        $medias = new Media();

        $form = $this->createForm(CatalogueType::class, $catalogue);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {

            // On récupère les images transmises
            $miniature = $form->get('miniature')->getData();
    
            
                // On génère un nouveau nom de fichier miniatureCatalogue
                $fichier1 = md5(uniqid()).'.'.$miniature->guessExtension();
                
                // On copie le fichier dans le dossier uploads
                $miniature->move(
                    $this->getParameter('images_directory'),
                    $fichier1
                );

               
                // On crée l'image dans la base de données
                $catalogue->setMiniature($fichier1);


                foreach($medias as $media){
                    // On récupère les images transmises
                    $media = $form->get('medias')->getData();
                    // On génère un nouveau nom de fichier medias
                    $fichier2 = md5(uniqid()).'.'.$media->guessExtension();

                    // On copie le fichier dans le dossier uploads
                    $media->move(
                        $this->getParameter('medias_directory'),
                        $fichier2
                    );
                    // On crée l'image dans la base de données
                    $img = new Media();
                    $img->setChemin($fichier2);
                    $catalogue->addMedia($img);

                    // $media->setChemin($fichier2);
                }


            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->persist($catalogue);

            $entityManager1 = $this->getDoctrine()->getManager();
            $entityManager1->persist($medias);

            $entityManager->flush();

            return $this->redirectToRoute('catalogue_index');
        }

        return $this->render('catalogue/new.html.twig', [
            'catalogue' => $catalogue,
            'form' => $form->createView(),
        ]);
    }

    #[Route('/{id}', name: 'catalogue_show', methods: ['GET'])]
    public function show(Catalogue $catalogue): Response
    {
        return $this->render('catalogue/show.html.twig', [
            'catalogue' => $catalogue,
        ]);
    }

    #[Route('/{id}/edit', name: 'catalogue_edit', methods: ['GET', 'POST'])]
    public function edit(Request $request, Catalogue $catalogue): Response
    {
        $form = $this->createForm(CatalogueType::class, $catalogue);
        $form->handleRequest($request);

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

            return $this->redirectToRoute('catalogue_index');
        }

        return $this->render('catalogue/edit.html.twig', [
            'catalogue' => $catalogue,
            'form' => $form->createView(),
        ]);
    }

    #[Route('/{id}', name: 'catalogue_delete', methods: ['POST'])]
    public function delete(Request $request, Catalogue $catalogue): Response
    { 
        
        $data = json_decode($request->getContent(), true);


        if ($this->isCsrfTokenValid('delete'.$catalogue->getId(), $data['_token'])) {
            
            // On récupère le nom de l'image
            $nom = $catalogue->getNom();
            // On supprime le fichier
            unlink($this->getParameter('images_directory').'/'.$nom);

            // On supprime l'entrée de la base
            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->remove($catalogue);
            $entityManager->flush();
        

        // On répond en json
            return new JsonResponse(['success' => 1]);
        }else{
            return new JsonResponse(['error' => 'Token Invalide'], 400);
        return $this->redirectToRoute('catalogue_index');
    }
}
} 

CatalogueType :

<?php
class CatalogueType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('nom', TextType::class ,[
                'attr' =>[
                    'placeholder' => "Nom du Catalogue",
                    'class' => 'form-control'
                ]
            ])
            ->add('miniature', FileType::class ,[
                'attr' =>[
                    'placeholder' => "Image Miniature pour le Catalogue",         
                    'class' => 'form-control',
                    // unmapped means that this field is not associated to any entity property
                    'mapped' => false,

                    // make it optional so you don't have to re-upload file
                    // every time you edit the Product details
                    'required' => false
                ]
            ])
            //add contrat subform
            ->add('medias',CollectionType::class,[
                'entry_type' => MediaType::class ,
                'entry_options'=>[
                    'label' =>false
                ],
                'by_reference' =>false,
                'allow_add' =>true,
                'allow_delete' =>true

            ])
            // ->add('medias', CollectionType::class,[
            //     'label' => false,
            //     'mapped' => false,
            //     'required' => false
            // ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Catalogue::class,
        ]);

    }
}

Form Media :

{{ form_start(form) }}

   <div class="form-row mb-4">
       <div class="form-group col-md-6">
           <label for="">Nom du média :</label>
           {{ form_widget(form.nom) }}
       </div>
       <div class="form-group col-md-6">
           <label for="">Ajout média : </label>
           {{ form_widget(form.chemin) }}
       </div>
   </div>
   <div class="form-row mb-4">
       <div class="form-group col-md-6">
           <label for="">Nom du média :</label>
           {{ form_widget(form.description) }}
       </div>
       <div class="form-group col-md-6">
           <label for="">Ajout média : </label>
           {{ form_widget(form.catalogues) }}
       </div>
   </div>



   <button class="btn">{{ button_label|default('Save') }}</button>
{{ form_end(form, {'render_rest': false}) }}

MediaType:

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('nom', TextType::class ,[
                'attr' =>[
                    'placeholder' => "Nom du média",
                    'class' => 'form-control'
                ]
            ]
            )
            ->add('chemin', FileType::class ,[
                'attr' =>[
                    'placeholder' => "Nom d'utilisateur",
                    'class' => 'form-control'
                ]
            ]
            )
            ->add('description', TextareaType::class ,[
                'attr' =>[
                    'placeholder' => "Description",
                    'class' => 'form-control'
                ]
            ]
            ) 

Can someone please help me to resolve this problem

Source: Ask PHP

LEAVE A COMMENT