Bonjour,

J'essaye de faire une page (= 1 semaine) pour réserver une ou des plongées. Il y a 6 jours possibles et pour chaque jour un cadre avec un bouton submit.
Si le système fonctionne correctement, je récupère les infos (nom, prénom, niveau) de l'utilisateur connecté (système inscription /connexion = OK) et cela s'affiche. On voit donc la liste des inscrits par jour.
Par ailleurs, je récupère en plus le jour (mardi ...) et la date de la plongée.
Le tout est mis en base dans une table DIVE.
Mon problème c'est que les boutons "inscription" (sauf le 1er) sont sans effet. Aucune erreur, mais aucun enregistrement ne va en base sauf avec le 1er bouton.
En fait, j'essaye en vain d'utiliser la fonction isClicked() de Symfony ...

Ce que je fais

Voilà le code mon controller

<?php

namespace App\Controller;

use App\Entity\Dive;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class DiveController extends AbstractController
{

    /**
     * @Route("/dive", name="inscrit")
     */
    public function inscrit(Request $request, EntityManagerInterface $manager)
    {

        $dive = new Dive();

        $start = new \DateTime("2021/03/14");

        $repo = $this->getDoctrine()->getManager()->getRepository(Dive::class);

        $mardis     = $repo->findBy(array('jour' => 'mardi'));
        $mercredis  = $repo->findBy(array('jour' => 'mercredi'));
        $jeudis     = $repo->findBy(array('jour' => 'jeudi'));
        $samedis    = $repo->findBy(array('jour' => 'samedi'));
        $samedis2   = $repo->findBy(array('jour' => 'samedi2'));
        $dimanches  = $repo->findBy(array('jour' => 'dimanche'));

        $form = $this->createFormBuilder()->getForm()->handleRequest($request);

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

                $clicked = $request->request->get('clicked');
                dd($clicked);
                $user = $this->getUser();

                $dive -> setNom($this->getUser()->getNom());
                $dive -> setPrenom($this->getUser()->getPrenom());
                $dive -> setNiveau($this->getUser()->getNiveau());
                    //dd($request);
                    if($clicked === 'mardi'){
                        $dive -> setDate($start->modify('+2 day'));
                        $dive -> setJour('mardi');
                    }

                    if($clicked === 'mercredi'){
                        $dive -> setDate($start->modify('+3 day'));
                        $dive -> setJour('mercredi');
                    }

                    if($request->request->get('jeudi')){
                        $dive -> setDate($start->modify('+4 day'));
                        $dive -> setJour('jeudi');
                    }

                    if($request->request->get('samedi')){
                        $dive -> setDate($start->modify('+6 day'));
                        $dive -> setJour('samedi');
                    }

                    if($request->request->get('samedi2')){
                        $dive -> setDate($start->modify('+6 day'));
                        $dive -> setJour('samedi2');
                    }

                    if($request->request->get('dimanche')){
                        $dive -> setDate($start->modify('+7 day'));
                        $dive -> setJour('dimanche');
                    }            

                $manager->persist($dive);
                $manager->flush();

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

        return $this->render('dive/dive.html.twig', [
            'start'     => $start,
            'form'      => $form->createView(),
            'mardis'    => $mardis,
            'mercredis' => $mercredis,
            'jeudis'    => $jeudis,
            'samedis'   => $samedis,
            'samedis2'  => $samedis2,
            'dimanches' => $dimanches
        ]);
    }
}

Et celui de mon template (une seule journée)

{% extends 'base.html.twig' %}

{% block title %}Réservation{% endblock %}

{% block body %}

    <div class="container">
        <h1>Réservation des plongées</h1>

        {% if is_granted('ROLE_USER') %}
        <h5>Bienvenue <strong>{{app.user.prenom }}</strong> dans la réservation des plongées.</h5>
        {% endif %}
        <br>

            <div class="row">

                <div class="col s12 m4">
                    <div class="card">
                        <div class="card-Title teal #bbdefb blue lighten-4">
                            <span class="card-title"><strong> Mardi</strong> - {{  start|date_modify("+2 day")|date("d/m/Y") }} </span>
                        </div>
                        <div class="card-content">
                            <table>
                                <thead>
                                    <tr>
                                        <th>Nom</th>
                                        <th>Prénom</th>
                                        <th>Niveau</th>
                                    </tr>
                                </thead>

                                <tbody>
                                    {% for mardi in mardis %}
                                        {% if mardi.date > start %}
                                            <tr>
                                                <td>{{mardi.nom}}</td>
                                                <td>{{mardi.prenom}}</td>
                                                <td>{{mardi.niveau}}</td>
                                            </tr>
                                        {% endif %}                 
                                    {% endfor %}
                                </tbody>                            
                            </table>
                            <br>
                                {{ form_start(form) }}
                                <button method="post" type='submit' name='clicked' value="mardi" class='waves-effect waves-light btn-small' style='background: #00cf67' label='mardi'>Inscription</button>                                                              
                                {{ form_end(form) }}
                        </div>
                    </div>

Ce que je veux

Si quelqu'un pouvait m'aider, tout particulièrement afin de pouvoir identifier chaque bouton "Inscription" afin que je puisse appliquer le bon traitement dans mon controller.
Un grand merci à celui ou ceux qui prendront quelques minutes pour me faire une réponse.

Ce que j'obtiens

Pour l'instant ... je suis bloqué :(

12 réponses


bidule
Réponse acceptée

Bonjour,

Pour éssayer de répondre à ta question normalement c'est pas sur le $request mais sur le $form que toi tester le isclicked()

$form->get('clicked')->isClicked()

Mais je pense tu cherches plus ceci

$form->get('clicked')->getData() // Récupère la VALUE du SUBMIT

Alors je vais peut-être te paraitre brusque ou désobligeant (mais il n'en est rien ) ;) désolé par avance :)

Mais à mon sens il y a un problème de conception à la base.

1- Tous tes "if" pourraient être remplacé par un "SWITCH CASE" mais dans l'absolu tu n'en à pas besoin

2- Tu initialises une variable avec une date fixe ? à cause d'une usine à gaz ?

    $start = new \DateTime(strtotime('Monday')); // date du Lundi de la semaine en cours

3- Tu n'as pas besoin d' insérer le jour de la semaine en base, utilise simplement une date, tu auras tout ce que tu as besoin avec en SQL.
Nota : Il faudra le traduire pour le QueryBuilder ;)
Nota 2: tu auras probablement besoin d'une extension pour doctrine pour manipulier les dates : https://github.com/beberlei/DoctrineExtensions/blob/master/config/mysql.yml

    SELECT
        Nom,
        Prenom,
        Niveau,
        DateReservation,
        DAYWEEK(DateReservation) AS numeroJour -- l'index commence à 0 donc Lundi = 0
    FROM
        reservations
    WHERE
        DateReservation
        BETWEEN
            DateStart -- Valeur envoyée, le Lundi de la semaine en cours
        AND
            DATE_ADD(DateStart, INTERVAL +6 DAY) -- Lundi de la semaine en cours + 6 jours = dimanche

En gros, tu sélectionnes tous les parametres + le jour de la semaine (exemple mardi = 1) ce qui te permettra des itérations plus facile

4- Du coup dans tu n'enverras qu'une seule variable à twig

    $reservationsSemaines = $repo->findAllBookingOfWeek($start) // Date du lundi de la semaine voulu

5- Pas besoin non plus de répéter ton template dans TWIG, RANGE est là pour t'aider

    <div class="row">
        {% for i in range(1, 6) %}
            <div class="col s12 m4">
                <div class="card">
                    <div class="card-Title teal #bbdefb blue lighten-4">
                        <span class="card-title"><strong> Mardi</strong> - {{  start|date_modify("+ ~ i ~ day")|date("d/m/Y") }} </span> <!-- start + i = Mardi sur la premiere itération -->
                    </div>
                    <div class="card-content">
                    ...
                    </div>
                </div>
            </div>
        {% endfor%}
    </div> 

6- Dans le même ordre ton tableau est beaucoup simple à gérer ( à tester quand même car fait de tête ;) )

    <tbody>
        {% for reservation in reservationsSemaines %}
            {% for resaJour in reservation.numeroJour = i %}
                <tr>
                    <td>{{resaJour.nom}}</td>
                    <td>{{resaJour.prenom}}</td>
                    <td>{{resaJour.niveau}}</td>
                </tr>
            {% endfor %}                 
        {% endfor %}
    </tbody>              

7- il en y va de même pour ton bouton (si tu souhaites continuer comme ça)

    {{ form_start(form) }}
        <button method="post" type='submit' name='clicked' value={{ i }} class='waves-effect waves-light btn-small' style='background: #00cf67' label='mardi'>Inscription</button>                                                              
    {{ form_end(form) }}

8- ce qui donne au final quelques chose comme ça (1 seule fois)

    <div class="row">
        {% for i in range(1, 6) %}
            <div class="col s12 m4">
                <div class="card">
                    <div class="card-Title teal #bbdefb blue lighten-4">
                        <span class="card-title"><strong> Mardi</strong> - {{  start|date_modify("+ ~ i ~ day")|date("d/m/Y") }} </span> <!-- start + i = Mardi sur la premiere itération -->
                    </div>
                    <div class="card-content">
                        <table>
                            <thead>
                                <tr>
                                    <th>Nom</th>
                                    <th>Prénom</th>
                                    <th>Niveau</th>
                                </tr>
                            </thead>

                            <tbody>
                                {% for reservation in reservationsSemaines %}
                                    {% for resaJour in reservation.numeroJour = i %}
                                        <tr>
                                            <td>{{resaJour.nom}}</td>
                                            <td>{{resaJour.prenom}}</td>
                                            <td>{{resaJour.niveau}}</td>
                                        </tr>
                                    {% endfor %}                 
                                {% endfor %}
                            </tbody>                            
                        </table>
                        <br>
                            {{ form_start(form) }}
                                <button method="post" type='submit' name='clicked' value={{ i }} class='waves-effect waves-light btn-small' style='background: #00cf67' label='mardi'>Inscription</button>                                                              
                            {{ form_end(form) }}
                    </div>
                </div>
            </div>
        {% endfor%}
    </div> 

7- Enfin ton controller sera bcp plus simple (un truc dans le genre)

    /**
 * @Route("/dive", name="inscrit")
 */
public function inscrit(Request $request, EntityManagerInterface $manager)
{

    $dive = new Dive();

    $start = new \DateTime(strtotime('Monday')); // date du Lundi de la semaine en cours

    $repo = $this->getDoctrine()->getManager()->getRepository(Dive::class);

    $reservationsSemaines = $repo->findAllBookingOfWeek($start) // Date du lundi de la semaine voulu

    $form = $this->createFormBuilder()->getForm()->handleRequest($request);

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

            $dive -> setNom($this->getUser()->getNom());
            $dive -> setPrenom($this->getUser()->getPrenom());
            $dive -> setNiveau($this->getUser()->getNiveau());

           // $form->get('clicked')->getData() récupère la VALUE du SUBMIT name ='clicked'

            $dive -> setDate($start->modify("+ $form->get('clicked')->getData() day"));

            $manager->persist($dive);
            $manager->flush();

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

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

en gros bon courage pour la suite, il y a probablement des petits couacs dans tout ça mais l'idée générale est là

Je ne comprends pas trop ton code, mais avec mes pauvres connaissances j'aurais tendance à faire un foreach(days as day) dans lequel je détermine la valeur et/ou le nom de mon boutton par day.

Bernard
Auteur

Bonjour,
Merci pour ta réponse.
Mon code dans le template marche bien. Je m'explique.
Ex avec le mardi ... je récupére en base (findBy dans le controller) les enregistrements ayant comme jour mardi.
Je les passe à la vue (en passant la variable ... en bas du controller)
Dans le template, j'ai une première boucle pour sélectionner l'enregistrement de chaque mardi parmi tous les mardi transmis par la variable.
La seconde boucle compare la date de référence ($start paramétrée dans le controller) avec la date de chaque mardi transmis.
Si la date du mardi concerné (celui de la semaine en cours) est > à la date indiquée dans le controller (= la date du dimanche passé) -> j'affiche.
Si la date est inférieure, c'est qu'il s'agit d'un mardi qui appartient à une semaine passée. Donc je n'affiche pas.
Je fais cela pour chaque jour de la semaine => cela me permet d'afficher jour par jour les inscriptions de lka semaine en cours.
Le dimanche suivant, je change la date de référence et le lundi matin, il n'y a aucun enregistrement affiché tant qu'il n'y a pas d'inscrit.
J'espère que tu vois mieux avec ces quelques explications.

Mais ma question n'était pas là.
Elle concerne l'utilisation de la fonction isClicked qui permet d'identifier le bouton qui a été cliqué (quand il y a plusieurs boutons).
Et là ... je sèche.

Peux tu montrer ton formulaire ?

Bernard
Auteur

Bonjour,
Merci ta réponse.
Le formulaire est ... vide.
Tu le trouves au début du controller.

$form = $this->createFormBuilder()->getForm()->handleRequest($request)

Je n'ai besoin d'aucun champ. Seulement d'un bouton submit (x6). Un par jour.
En effet je récupère les informations du USER connecté ( $user = $this->getUser(); ). Il n'a rien à saisir.
A la fin je mets en base ces infos + le jour et la date via le bouton submit qui est cliqué.
C'est justement cela que je n'arrive pas à utiliser avec la méthode isClicked.
Cette méthode identifie le bouton cliqué et à partir de là je trouve la date et le jour.
Mais je n'arrive pas à trouver la solution pour dire ... c'est le bouton Jeudi qui a été cliqué
donc le jour est "jeudi" et la "date = $start + 4 jours".
OK ?

Ok donc si je comprends bien ta problématique, tu as un utilisateur connecté qui peut s'inscrire à une évènement selon le jour qu'il souhaite (du lundi au samedi)
Tu as une grille avec tes 6 jours donc 6 boutons sur lesquels tu as une value différente, mais un name identique?
Dans ce cas je passerai la value en $_SESSION['selected_day'] pour ainsi récupérer la valeur du bouton cliquer et faire la suite de ton script par rapport à cette valeur.
De mon point de vue de débutant c'est plus un problème d'algorithme que de code pure.

Edit:
Ce qui me parait étrange c'est que tu parles d'un template dans lequel tu as des valeurs défini en dur.

Bernard
Auteur

Merci Kurdtkobane pour ton message.
Non, ... je te répète. Il y a une méthode isClicked sur le site Symfony.com qui dit qu'on peut identifier le bouton cliqué avec cette méthode.
Mais j'ai beau faire et refaire ... je n'arrive pas à trouver la bonne syntaxe pour l'utiliser.
C'est cette syntaxe que je cherche.

Maintenant, pour répondre à tes questions / remarques, pour mon template, je pourrais inventer une usine à gaz pour trouver la date du jour sélectionné.
J'ai choisi de faire plus simple. Mais je ne code pas pour autant en dur dans le template. D'ailleurs, ce serait impossible car les dates changent chaque semaine.
Au début de mon controller, je déclare une variable ... $start. C'est la date du dimanche. On pourrait me dire que c'est un peu "basique" mais moi ça me suffit.
La semaine qui suit, c'est celle durant laquelle il y aura les plongées. Les plongeurs s'inscrivent à partir de lundi matin pour la semaine en cours.
Donc pour le mardi la date de la plongée c'est $start + 2 jours. Le jeudi c'est $start + 4 jours. Et j'affiche facilement chaque date à l'écran avec la méthode "modify" date (cf mardi).
Le dimanche suivant je change la valeur de $start et ça recommence pour la nouvelle semaine.
Quant aux plongées affichées (celles qui sont réservées par les adhérents pour la semaine en cours) j'ai un filtre dans le controleur avec mon findBy (tout ce qui est
avant le dimanche de référence ($start) n'est pas affiché mais reste en base de données comme ça je peux faire des requêtes et savoir le nombre de plongées par mois , ... etc.
OK ?

Si tu veux bien comprendre ma logique de programmation :

  • regarde le $start
  • le findBy -> la sélection des plongées par jour (mardi, mercredi, ...etc)
  • le formulaire transmis qui est ... vide et pour lequel je n'affiche qu'un bouton submit (pour chaque journée) sans aucun champ de saisie car je récupère les valeurs
    avec $user = $this->getUser() du user connecté au moment de la réservation de ses plongées
  • le passage des paramètres à la vue (en bas du controller)
  • la récupération et la sélection des éléments voulus dans la vue (tout est configuré dans le tbody du template)

J'espère que ça t'aura éclairé ... sur ma manière de faire.

Pour conclure, je te répète que c'est la syntaxe de isClicked que je cherche (dans le controller et dans mon template). Si je la trouve, mon problème est réglé.

Ok je comprends ce que tu veux faire. Seulement je suis nul en dev, ça fait 15 jours que je commence PHP seulement. Mais ton get('clicked') il récupère pas la value de ton bouton?
Si c'est la cas tu as une value dans ton template qui est inscrite en dur puisqu'elle est défini par mardi.
Quand je lis la documentation de Synfony ici https://symfony.com/doc/current/form/multiple_buttons.html de ce que je comprends de la méthode et de ce que tu me dis c'est qu'elle permet avec le même nom de faire une get d'une valeur différente.
Je me trompe peut être en disant que si tu te bases sur le template ta value est égale à mardi.
Je finirai en disant que la seule différence de syntaxe que je vois entre ton code est la doc de Symfony c'est ce passage avec tes conditions et avant le return:

$nextAction = $form->get('saveAndAdd')->isClicked()
        ? 'task_new'
        : 'task_success';

Ensuite dans ton controller sur ton $start je vois un \ avant DateTime, c'est normal? Ensuite pourquoi ton datetime est un jour en dur qui correspond bien à un dimanche, mais n'est il pas plus judicieux d'extraire dans ta variable le 7 ième jour d'une semaine ou le 1er selon le format, afin que ton code soit viable dans 10 ans? A quoi correspond dd($clicked) après la première déclaration de $clicked?

Je suis désolé si je te fais perdre ton temps, mais en essayant de comprendre ce que tu fais ça me permet d'apprendre. Et peux être que ça débloquera la situation.
Et du peu que j'ai compris et de ce que je connais ton get renvoie la valeur du nom de ton bouton et si cette valeur dans ton template = mardi alors les autres bouton risque d'avoir la même valeur et donc les conditions ne se remplissent pas.

Cordialement

Bernard
Auteur

Bonsoir Bidule,
Un très grand merci pour avoir passé autant de temps à me faire une réponse vraiment fouillée.
Cela semble beaucoup plus sophistiqué que mon code assez "basique".
Je vais regarder tout ce que tu m'indiques et tester.
Encore merci pour ton aide.

Avec plaisir, il y a encore des choses optimisables (et à corriger car fait de tête).

On a tous débuté en pensant faire au plus simple (qui au final devient complexe ...)

Il faudra prendre un peu de temps pour traduire la requete SQL pour doctrine et des petites choses dans TWIG.

Bernard
Auteur

Sujet résolu

Bonsoir.
Il ne te faut pas juste dire: Sujet résolu.
Il te faut valider une ou des réponses qui t'ont permises de résoudre ton problème afin que ton sujet soit marqué comme résolu.