Bonjour,

J'ai un petit souci de création d'objets. (je précise que je suis sur symfony3 et doctrine2)
J'ai une entité Groupe et une entité PropriétéGroupe.

Grâce un formulaire PropriétéGroupeType, l'utilisateur donne le nombre de groupes qu'il souhaite.

Mon but est ensuite de fournir à l'utilisateur un seul formulaire où il pourra décrire ses Groupes (donner un nom, un commentaire et un effectif max)

Je m'étais donc dit chouette, je n'ai qu'à faire une boucle du genre :

for($i=0;$i<$nbgpe;$i++){
$groupe.$i = new Groupe();
$form.$i = $this->createForm(GroupeType::class, $groupe.$i);
}
        return $this->render('ProfBundle:Groupe:newGroupe.html.twig', array(
            'form' => $form->createView(),
        ));

J'ai donc 2 problèmes :
1) Il semble impossible d'utiliser une syntaxe comme celle-ci !
2) Que passer à ma vue étant donné que je n'ai pas qu'un $form ?

Je vous remercie par avance pour toute piste éventuelle !
Nans

16 réponses


skp
Réponse acceptée

Pour persister tu dois faire :

//après validation du formulaire
$groupes = $form->getData()["groupes"]; //variable $groupes contient un tableau d'objet Groupe
$em = $this->get("doctrine")->getManager();
//comme $em->persist(); n'accepte pas de tableau tu dois parcourir ton tableau et persister 1 par 1 tes objets
foreach($groupes as $groupe)
{
    $em->persist($groupe);
}
$em->flush();

Si tu crée un tableau que tu remplis ?

$form = []; 
...
$form[$i] = $this->createForm(GroupeType::class, $groupe.$i);
nans
Auteur

Bonjour et merci pour cette réponse. Le problème maintenant est que je ne peux pas donner un tableau à createview :

Error: Call to a member function createView() on a non-object

Bonjour, une des solutions c'est de créer un formulaire intermédiaire qui lui va contenir une collection de ton formulaire.
Exemple (n'oublie pas de renommer IntermediaireType si tu utilises cette solution) :

class IntermediaireType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add("groupes", "collection", ["entry_type" => GroupeType::class]);
    }
}

Dans ton controller :

for($i=0;$i<$nbgpe;$i++){
    $data["groupes"][] = new Groupe();
}
$form = $this->createForm(IntermediaireType::class, $data);

En espérant que ça t'aide.

nans
Auteur

Merci pour cette réponse ! J'espère pouvoir tester ça ce soir,... après mes copies.

Sans les aides comme celles-ci et les tutos,... les débutants comme moi seraient fichus, merci encore.

nans
Auteur

Je n'ai pas encore la solution mais voici la syntaxe correcte de symfony3 pour le collectionType :

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add("groupes", CollectionType::class, array(
            'entry_type' => GroupeType::class,
            'allow_add' => true,
            'allow_delete' => true,
            'by_reference' => false
            )
        );
    }

Voici l'erreur que j'obtiens : The form's view data is expected to be an instance of class Bundle\Entity\Groupe, but is a(n) array. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) array to an instance of Bundle\Entity\Groupe.

nans
Auteur

Alors ça avance !!!
Dans mon controller :

    public function newAction(Request $request, $nbgpe){
        for($i=0;$i<$nbgpe;$i++){
        $data["groupes"][] = new Groupe();
        }
        //var_dump($data);
        $form = $this->createForm(RelaiType::class, $data);
        $form->add('save', SubmitType::class, array('label' => 'Valider'));
        //var_dump($form);
        return $this->render('Bundle:Groupe:newGroupe.html.twig', array(
            'form' => $form->createView(),
            'groupe' => $data
        ));   
    } 

Dans ma vue :

{% extends 'Bundle::base.html.twig' %}
{% block body %}

{{ form_label(form.groupes) }}
{{ form_errors(form.groupes) }}

<ul>
{% for groupeField in form.groupes %}
    <li>
        {{ form_errors(groupeField) }}
        {{ form_widget(groupeField) }}
    </li>
{% endfor %}
</ul>
{% endblock %}

Dans mon RelaiType :

class RelaiType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('save', SubmitType::class, array('label' => 'Valider'))  
            ->add("groupes", CollectionType::class, array(
                'entry_type' => GroupeType::class,
                'allow_add' => true,
                'allow_delete' => true
                 ));

    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => null
        ));
    }
}

Mon problème : Impossible d'avoir mon bouton submit ! J'ai essayé dans le relaiType, dans le controller, dans le GroupeType (ici, ça m'en met autant que de groupe, logique).

Une idée ?

Dans ta vue tu as oublié {{ form_start(form) }} et {{ form_end(form) }} non ?

nans
Auteur

Effectivement c'est mieux ! Je ne suis malgré tout pas au bout de mes surprises puisque je n'arrive pas à envoyer mes données (alors que $_POST existe (il me renvoie un tableau vide, avec chaque groupe vide)).
J'ai ajouté dans ma vue un form action :

<form action="{{ path("Faire_Groupe")}}" method="POST"> 

Mon but étant de renvoyer au controller les données pour faire l'enregistrement des groupes dans la BDD.

Le problème c'est que mon $_POST ne prend aucune de mes données. Mon formulaire garde ce que j'ai pré rempli même lorsque j'actualise la page, ce qui ne me semble pas normal.

Dans mon controller :

        if(!empty($_POST)){
            echo'plein';
        }
                if(empty($_POST)){
            echo'vide';
        }
        for($i=0;$i<3;$i++){
        $data["groupes"][] = new Groupe();
        }
        //var_dump($data);
        $form = $this->createForm(RelaiType::class, $data);
        //$form->add('submit', SubmitType::class, array('label' => 'Test'));
        //var_dump($form);
        $form->handleRequest($request);
        var_dump($_POST);
        if (isset($_POST['submit'])) {
            //var_dump($form);
            foreach ($data as $value){
            $em = $this->getDoctrine()->getManager();
            $em->persist($value);
            $em->flush();        
            }
            return $this->render('structureBundle:Defaults:index.html.twig');
        }  

Du coup mon controller commence à être chargé de lignes inutiles de différents tests...

Je m'en remets encore à vous ! Au cas où vous voyez une erreur flagrante.

Nans

Dans ton controller, si tu fais "dump($form->getData())" tu obtiens quoi ?

nans
Auteur

Ah ça ça marche, j'ai bien les données de mon formulaire. Je n'ai pas d'id à mes groupes mais le reste est là

nans
Auteur

En fait il y a un problème de tableau et d'objet. J'ai l'impression que je ne créé pas d'objet dans ma boucle, c'est pour ça que je n'ai pas d'id :

$data["groupes"][] = new Groupe();

Tu n'as pas persisté tes objets dans ta bdd. Par conséquent, c'est normal qu'ils n'ont pas d'id.

nans
Auteur

En fait je me suis complètement perdu. Entre tableau, objet,... J'ai essayé de persisté avec mon foreach mais en fait j'arrive pas à extraire mes données pertinentes avec getData.
Enfin bref, il faut que je potasse encore

nans
Auteur

En fait j'arrive bien à préremplir mes attributs de groupes, je le vois bien dans le var_dump. Quand j'essaye de persister, il me dit :
EntityManager#persist() expects parameter 1 to be an entity object, array given.

nans
Auteur

Punaise... Merci ! Je n'aurais jamais réussi sans ton aide !