[RESOLU] [Symfony2] Form field à sauver et utilisé dans Query Builder

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

07 mai 2013, 11:51

- as-tu vraiment besoin du champs hidden "course_id" ? Tu en fait quoi, tu t'en sers ou ?
C'est la toute ma question :P, tu me dis depuis le début que je n'en ai pas besoin, je suis prêt à te croire sur parole mais je ne comprends pas comment, à la réception du formulaire soumis, je peux savoir sur quel cours porte mon compte-rendu. Car quand je sauve mon objet ClassSession, je dois conserver la relation vers le Cours. Je m'en sers donc dans le createAction (après soumission du formulaire) pour récupérer l'objet Course qui correspond à l'ID transmis:
        $courseId = $form->get('course_id')->getData();
        $course = $this->getCourseRepository()->find($courseId);
        $entity->setCourse($course);
C'est là que je ne comprends comment je peux me passer de cette information dans le formulaire, vu que dans le createAction je crée une instance de ClassSession vide avant de binder mon formulaire avec la requête, si je ne transmets pas cet ID dans le formulaire, je ne sais pas comment récupérer cette info. Est-ce qu'il y a un moyen de conserver l'objet ClassSession initialisé dans le newAction (avant sousmission du formulaire) ?
    /**
     * Creates a new ClassSession entity.
     *
     * @Route("/create", name="classsession_create")
     * @Method("POST")
     * @Template("VirguleMainBundle:ClassSession:new.html.twig")
     */
    public function createAction(Request $request) {
        $entity = new ClassSession();     // ==============================> Ici je réceptionne le formulaire, et j'ai besoin d'un objet ClassSession pour le "createForm". Donc j'en crée un nouveau et donc l'attribut "course" vaut null. Est-il possible ici de réutiliser l'objet ClassSession qui a été initialisé avec le bon cours dans newAction ?
        $organizationBranchId = $this->getSelectedOrganizationBranchId();
        $currentTeacher = $this->getConnectedUser();
               
        $form = $this->createForm(new ClassSessionType($this->getDoctrine(), $organizationBranchId, $currentTeacher), $entity, array(
    'em' => $this->getDoctrine()->getManager(),
));
- pas bien compris ton histoire de ArrayCollection ?
C'est dans l'appel de la méthode "createNamed", tu avais mis ça :
$form->add($this->factory->createNamed('classSessionStudents', 'entity', $data['courseId'], array(
C'est l'utilisation du $data['courseId'] qui posait problème, de ce que j'ai compris comme j'ai une relation ManyToMany cet champ là attend une collection si tu lui passes des données. Finalement en lisant la doc de l'API j'ai compris que je n'avais pas besoin de ce paramètre, j'ai donc passé une ArrayCollection vide, dans ton dernier exemple tu as mis null, je pense que ça revient au même.

Merci pour ton aide en tout cas :)

Mammouth du PHP | 568 Messages

07 mai 2013, 14:11

C'est la toute ma question :P, tu me dis depuis le début que je n'en ai pas besoin, je suis prêt à te croire sur parole mais je ne comprends pas comment, à la réception du formulaire soumis, je peux savoir sur quel cours porte mon compte-rendu. Car quand je sauve mon objet ClassSession, je dois conserver la relation vers le Cours. Je m'en sers donc dans le createAction (après soumission du formulaire) pour récupérer l'objet Course qui correspond à l'ID transmis:
Normalement si ton schéma est bien fait, le fait d'initialiser le cours dans le ClassSession doit suffire (avec le persist en cascade), c'est doctrine qui va faire le reste.

Ensuite, j'ai l'habitude de gérer la création en une seul méthode "create" or "new" peut importe, et de se fait, à chaque fois que j'initialise mon entité, celle-ci possède toujours les informations voulut, et c'est le fait de binder qui peut éventuellement modifier les valeur.

Voici un exemple d'action dans un de mes projets:
/**
     * @Route("/client/creer", name="client_new")
     * @Method({"GET", "POST"})
     * @Secure(roles="ROLE_RESPONSABLE")
     */
    public function newAction()
    {
        $request = $this->get('request');

        $typeParticulier = $this->get('inextenso.manager.typeclient')->getById(TypeClient::PARTICULIER);

		$client = new Client();
		//dans tous les cas mon entité client possède le type initialiser, MAIS l'utilisateur a potentiellement changé la valeur via un select, et c'est le bind plus bas qui va surcharger la valeur
		$client->setType($typeParticulier);
		
        $form = $this->createForm(new ClientType(), $client);
        
		//POST & bind
		if ($request->isMethod('POST')) {
			$form->bind($request);

			if ($form->isValid()) {
				$this->get('inextenso.manager.client')->save($client, $dossier);
				$this->get('session')->getFlashBag()->add('notice_success', 'Le client à été créée.');

				return $this->redirect($this->generateUrl('client_edit', array('id' => $client->getId())));
			}
		}

		return $this->get('templating')->renderResponse('InExtensoNotesFraisBundle:Client:form.html.twig',
            array(
                'entity' => $entity,
                'form' => $form->createView()
            )
        );        
    }

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

10 mai 2013, 09:49

Normalement si ton schéma est bien fait, le fait d'initialiser le cours dans le ClassSession doit suffire (avec le persist en cascade), c'est doctrine qui va faire le reste.
Initialiser l'objet ClassSession avec l'objet Cours fonctionne, il est correctement sauvé. Mais mon objet cours provient d'un paramètre passé dans l'url, donc je l'ai en GET, mais je ne l'ai plus une fois le formulaire soumis, d'où mon champ hidden.
Ensuite, j'ai l'habitude de gérer la création en une seul méthode "create" or "new" peut importe, et de se fait, à chaque fois que j'initialise mon entité, celle-ci possède toujours les informations voulut, et c'est le fait de binder qui peut éventuellement modifier les valeur.
Je n'avais pas pensé à faire ça, je suivais bêtement la structure créée par le générateur CRUD de Symfony. Dans ton exemple, si à la place de ta constante TypeClient::PARTICULIER tu avais un paramètre récupéré depuis l'url à l'initialisation du formulaire, n'aurais-tu pas besoin de le conserver dans le formulaire pour le récupérer à la sortie ?

Quoiqu'il en soit je passe le sujet en résolu, mon problème de base est réglé et j'ai appris des trucs sur les formulaires. Je vais essayer de le modifier maintenant pour avoir une liste déroulante de cours si jamais l'ID de cours n'est pas récupéré via un paramètre GET (formulaire générique) et recharger la liste des apprenants inscrits à chaque changement de cours dans cette liste.

Merci pour ton aide :)