Partage
  • Partager sur Facebook
  • Partager sur Twitter

[MVC] Nombre variable de clause Where

Sujet résolu
    18 novembre 2019 à 16:42:52

    Bonjour,

    J'essaye de basculer mon développement en MVC car c'est plus facile pour l'implémentation de nouvelled fonction et la maintenabilité et d'autre chose encore sauf que j'ai un petit problème.

    J'ai un module de recherche avec 6 filtres possibles.

    Ce que j'ai fait fonctionne s'il n'y a qu'un filtre de sélectionner mais pas s'il y en a plusieurs...

    Voici une partie de mon controlleur :

    if (isset($_POST['search_bat']) && $_POST['search_bat'] !== "") {
        $currentBatiment = $_POST['search_bat'];
        $idBatiment = getIDBatiment($_POST['search_bat']);
        $demandes = getDemandesWhereBatiment($idBatiment);
    }
        
    if (isset($_POST['search_nom']) && $_POST['search_nom'] !== "") {
        $currentVisiteur = $_POST['search_nom'];
        $nom = substr($currentVisiteur, 0, strpos($currentVisiteur, ','));
        $prenom = substr($currentVisiteur, strpos($currentVisiteur, ',') + 2);
        $idVisiteur = getIDVisiteur($nom, $prenom);
        //$demandes = getDemandesWhereBatiment($idBatiment);
    }
        
    if (isset($_POST['search_ste']) && $_POST['search_ste'] !== "") {
        $currentSociete = $_POST['search_ste'];
        $idSociete = getIDSociete($_POST['search_ste']);
        //$demandes = getDemandesWhereBatiment($idBatiment);
    }
        
    if (isset($_POST['search_bat']) && $_POST['search_bat'] !== "") {
        $currentBatiment = $_POST['search_bat'];
        $idBatiment = getIDBatiment($_POST['search_bat']);
        //$demandes = getDemandesWhereBatiment($idBatiment);
    }
        
    $nbDemandes = sizeof($demandes);
    
    for ($i = 0; $i < $nbDemandes; $i++){
        $visiteur = getVisiteurFromDemande($demandes[$i]['ID_Demande']);
        $visiteursVenus[$i]= $visiteur['Nom_Visiteur'] . ", " . $visiteur['Prenom_Visiteur'];
        $typeVisiteursVenus[$i] = getTypeVisiteurFromVisiteur($visiteur['ID_Visiteur'])['Nom_Type_Visiteur'];
        $numeroDemande[$i] = $demandes[$i]['Num_Enregistrement'];
        $societesVenues[$i] = getSocietyFromVisiteur($visiteur['ID_Visiteur'])['Nom_Societe'];
        $batimentsVisites[$i] = getBatimentFromDemande($demandes[$i]['ID_Demande'])['Nom_Batiment'];
        $planDemande[$i] = $demandes[$i]['Plan_Prevention'];
        $arrivee[$i] = $demandes[$i]['Date_Deb_Prevue'] . " à " . $demandes[$i]['H_Deb_Prevue'];
        $fin[$i] = $demandes[$i]['Date_Fin_Prevue'] . " à " . $demandes[$i]['H_Fin_Prevue'];
        $commentaire[$i] = $demandes[$i]['Comm_Demandeur'];
    }
    

    Et j'avoue que je vois pas vraiment comment faire, si ce n'est répéter les clause IF imbriquées ce qui serait hyper degueulasse...

    En gros je me demande comment faire si on filte et sur la société ($_POST['search_ste'] et sur un bâtiment par exemple ($_POST[{search_bat'])...

    Si qqun peut m'aider à choper la logique ou m'aiguiller svp... Merci d'avance

    PS : Je suis sûre que c'est un truc tout con...

    • Partager sur Facebook
    • Partager sur Twitter

    Parfois, arrêter 5 minutes son développement permet de mieux repartir face à un problème ;)

      18 novembre 2019 à 17:00:12

      Salut !

      Plutôt que de voir ça comme des clauses WHERE, prends-les comme des conditions indépendantes. Là où tu imagines WHERE idBatiment = 324 WHERE nomBatiment = 'Immeuble d'habitation de la Rue du Sansonnet 15', ce qui ne fonctionne effectivement pas, tu peux penser à WHERE idBatiment = 324 AND nomBatiment = 'Immeuble d'habitation de la Rue du Sansonnet 15'.

      De manière simple, si tu as déjà un WHERE ou si ce n'est pas la première condition que tu dois mettre dans ta requête, tu ne mets pas WHERE, mais AND.

      • Partager sur Facebook
      • Partager sur Twitter
        18 novembre 2019 à 20:01:17

        salut pour simplifier la ligne 1 ainsi que celles lui ressemblant tu peux faire ceci :

        if (isset($_POST['search_bat']) && $_POST['search_bat'] !== "") {
            // condition ici
        }
        
        // peut être simplifié ainsi :
        
        if (!empty($_POST['search_bat'])) {
          // condition ici
        }



        • Partager sur Facebook
        • Partager sur Twitter
          18 novembre 2019 à 21:18:35

          > peut être simplifié ainsi :

          Oui et non : les deux codes ne sont pas strictement équivalents. Dans l'autre sujet tu encourages l'usage de ===/!== mais tu oublies que pour empty, '0' et [] sont aussi des valeurs vides ...


          Peux pas générer ta clause WHERE au fur et à mesure de tes if via un tableau ? Genre :

          $conds = ['1=1'];
          if (isset($_POST['search_bat']) &amp;&amp; $_POST['search_bat'] !== "") {
              $conds[] = 'bat = ' . $bdd-&gt;quote($_POST['search_bat']);
          }
          if (isset($_POST['search_nom']) &amp;&amp; $_POST['search_nom'] !== "") {
              $conds[] = 'nom = ' . $bdd-&gt;quote($_POST['search_nom']);
          }
          if (isset($_POST['search_ste']) &amp;&amp; $_POST['search_ste'] !== "") {
              $conds[] = 'ste = ' . $bdd-&gt;quote($_POST['search_ste']);
          }
          $stmt = $bdd-&gt;query('SELECT * FROM table WHERE ' . implode(' AND ', $conds));
          

          Et pourquoi chercher les id à partir des "noms" ? Tables différentes ?

          -
          Edité par julp 18 novembre 2019 à 21:32:23

          • Partager sur Facebook
          • Partager sur Twitter
            19 novembre 2019 à 9:37:12

            Ymox a écrit:

            Salut !

            Plutôt que de voir ça comme des clauses WHERE, prends-les comme des conditions indépendantes. Là où tu imagines WHERE idBatiment = 324 WHERE nomBatiment = 'Immeuble d'habitation de la Rue du Sansonnet 15', ce qui ne fonctionne effectivement pas, tu peux penser à WHERE idBatiment = 324 AND nomBatiment = 'Immeuble d'habitation de la Rue du Sansonnet 15'.

            De manière simple, si tu as déjà un WHERE ou si ce n'est pas la première condition que tu dois mettre dans ta requête, tu ne mets pas WHERE, mais AND.

            Bonjour,

            Oui ca je concois parfaitement, mais ma question c'est est-ce qu'il faut faire une fonction avec 2 conditions, 3 conditions etc... ou est-ce possible de faire une fonction avec un nombre variable de condition qui sont sur des tables différentes ?

            julp a écrit:

            > peut être simplifié ainsi :

            Oui et non : les deux codes ne sont pas strictement équivalents. Dans l'autre sujet tu encourages l'usage de ===/!== mais tu oublies que pour empty, '0' et [] sont aussi des valeurs vides ...


            Peux pas générer ta clause WHERE au fur et à mesure de tes if via un tableau ? Genre :

            $conds = ['1=1']; if (isset($_POST['search_bat']) &amp;&amp; $_POST['search_bat'] !== "") { $conds[] = 'bat = ' . $bdd-&gt;quote($_POST['search_bat']); } if (isset($_POST['search_nom']) &amp;&amp; $_POST['search_nom'] !== "") { $conds[] = 'nom = ' . $bdd-&gt;quote($_POST['search_nom']); } if (isset($_POST['search_ste']) &amp;&amp; $_POST['search_ste'] !== "") { $conds[] = 'ste = ' . $bdd-&gt;quote($_POST['search_ste']); } $stmt = $bdd-&gt;query('SELECT * FROM table WHERE ' . implode(' AND ', $conds)); 

            Et pourquoi chercher les id à partir des "noms" ? Tables différentes ?

            -
            Edité par julp il y a environ 11 heures


            Bonjour,

            Je comprends la logique du tableau mais les requetes ne doivent pas etre fait dans le modele ? La fonction doit donc recevoir un tableau de condition du coup ?

            Oui, il y a pas mal de tables différentes donc je récupère les ID à partir des noms dans une table qui ne contient que ces deux champs là

            EDIT : Par rapport à la solution proposée par JULP, ne faudrait-il pas que je fasse un fonction qui requête sur toute ma base avec toute mes liaisons et lui passer les conditions sous forme de tableau en paramètre de la fonction ?

            -
            Edité par lindadu01 19 novembre 2019 à 9:46:43

            • Partager sur Facebook
            • Partager sur Twitter

            Parfois, arrêter 5 minutes son développement permet de mieux repartir face à un problème ;)

              19 novembre 2019 à 9:45:44

              lindadu01 a écrit:

              Oui ca je concois parfaitement, mais ma question c'est est-ce qu'il faut faire une fonction avec 2 conditions, 3 conditions etc... ou est-ce possible de faire une fonction avec un nombre variable de condition qui sont sur des tables différentes ?

              C'est tout à fait possible d'avoir des contraintes sur plusieurs tables. Ce n'est absolument pas incompatible avec ce que julp propose, d'ailleurs.

              • Partager sur Facebook
              • Partager sur Twitter
                19 novembre 2019 à 10:48:45

                Grace à Julp, voici ce que j'ai fait et qui fonctionne :

                Mon controlleur :

                if (isset($_POST['search_bat']) && $_POST['search_bat'] !== "") {
                    $currentBatiment = $_POST['search_bat'];
                    $conds[] = 'batiment.Nom_Batiment = "' . $_POST['search_bat'] . '"';
                }
                    
                if (isset($_POST['search_nom']) && $_POST['search_nom'] !== "") {
                    $currentVisiteur = $_POST['search_nom'];
                    $nom = substr($currentVisiteur, 0, strpos($currentVisiteur, ','));
                    $prenom = substr($currentVisiteur, strpos($currentVisiteur, ',') + 2);
                    $conds[] = 'visiteur.Nom_Visiteur = "' . strtoupper($nom) . '"';
                    $conds[] = 'visiteur.Prenom_Visiteur = "' . $prenom . '"';
                }
                    
                if (isset($_POST['search_ste']) && $_POST['search_ste'] !== "") {
                    $currentSociete = $_POST['search_ste'];
                    $conds[] = 'societe.Nom_Societe = "' . $_POST['search_ste'] . '"';
                }
                $demandes = getDemandes($conds); 

                Mon modele :

                function getDemandes($conditions)
                {
                    $dataBase = DBConnect();
                    $requete = $dataBase->query(
                        'requete avec plusieurs jointures
                                                      
                        WHERE ' . implode(' AND ', $conditions) . '
                        GROUP by d.ID_Demande, contact.Nom_Contact, contact.Prenom_Contact
                        ORDER BY Num_Enregistrement ASC');
                    $demandes = $requete->fetchAll();
                    $requete->closeCursor();
                    return $demandes;
                }




                -
                Edité par lindadu01 19 novembre 2019 à 10:49:29

                • Partager sur Facebook
                • Partager sur Twitter

                Parfois, arrêter 5 minutes son développement permet de mieux repartir face à un problème ;)

                  19 novembre 2019 à 10:54:14

                  J'espère que tu as bien sécurisé les contenus de $_POST, parce que là tu concatènes à tout va, et donc tu as autant de risques d'injection SQL…

                  • Partager sur Facebook
                  • Partager sur Twitter
                    19 novembre 2019 à 12:53:56

                    Après réflexion et suite à la réponse de Ymox, je suis passé sur des requêtes préparées en suivant la même logique :

                    controller :

                        if (isset($_POST['search_bat']) && $_POST['search_bat'] !== "") {
                            $currentBatiment = $_POST['search_bat'];
                            $champs[] = 'Nom_Batiment = :nomBatiment';
                            $conds['nomBatiment'] = $_POST['search_bat'];
                        }
                    
                        if (isset($_POST['search_nom']) && $_POST['search_nom'] !== "") {
                            $currentVisiteur = $_POST['search_nom'];
                            $nom = substr($currentVisiteur, 0, strpos($currentVisiteur, ','));
                            $prenom = substr($currentVisiteur, strpos($currentVisiteur, ',') + 2);
                            $champs[] = 'Nom_Visiteur = :nomVisiteur';
                            $conds['nomVisiteur'] = strtoupper($nom);
                            $champs[] = 'Prenom_Visiteur = :prenomVisiteur';
                            $conds['prenomVisiteur'] = $prenom;
                        }
                    
                        if (isset($_POST['search_ste']) && $_POST['search_ste'] !== "") {
                            $currentSociete = $_POST['search_ste'];
                            $champs[] = 'Nom_Societe = :nomSociete';
                            $conds['nomSociete'] = $_POST['search_ste'];
                        }
                    
                        if (isset($_POST['search_type']) && $_POST['search_type'] !== "") {
                            $currentType = $_POST['search_type'];
                            $champs[] = 'Nom_Type_Visiteur = :nomType';
                            $conds['nomType'] = $_POST['search_type'];
                        }
                    
                        $demandes = getDemandes($champs, $conds);  

                    Modele :

                    function getDemandes($champs, $conditions)
                    {
                        // voir pour essayer de le transformer en prepare
                        $dataBase = DBConnect();
                        $requete = $dataBase->prepare(
                            'Requete avec jointure
                            WHERE ' . implode(' AND ', $champs) . '
                            GROUP by d.ID_Demande, contact.Nom_Contact, contact.Prenom_Contact
                            ORDER BY Num_Enregistrement ASC');
                        $requete->execute ($conditions);
                        $demandes = $requete->fetchAll();
                        $requete->closeCursor();
                        return $demandes;




                    • Partager sur Facebook
                    • Partager sur Twitter

                    Parfois, arrêter 5 minutes son développement permet de mieux repartir face à un problème ;)

                      19 novembre 2019 à 14:17:07

                      C'est bien, juste quelques "remarques" :

                      • le closecursor ne devrait pas être nécessaire, ce qui te permettrait de directement retourner le fetchAll (ça fait toujours gagner 2 lignes)
                      • faire attention aux substr, aux strpos plutôt, si jamais ta chaîne n'avait pas de , voire plusieurs (ta condition en serait systématiquement fausse et la requête ne renverrait rien)
                      • strtoupper n'est pas compatible avec de l'UTF-8, à remplacer par mb_strtoupper ou mb_convert_case sachant toutefois que si ta colonne est insensible à la casse (via un interclassement suffixé de _ci pour MySQL par exemple), forcer la chaîne en majuscules serait superflu
                      • Partager sur Facebook
                      • Partager sur Twitter

                      [MVC] Nombre variable de clause Where

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown