Partage
  • Partager sur Facebook
  • Partager sur Twitter

plusieurs IN pour plusieurs colonnes

Sujet résolu
    15 octobre 2021 à 13:25:33

    Bonjour à tous

    voilà j'ai plus ou moins avancé sur mon projet mais j'ai un petit problème

    En fait j'essai de filtrer mes "sorties" selon des checkboxes ( à l'arrivé de la page on affiche tout) puis ensuite via les checkboxes on filtre

    actuellement cela marche si on choisi "nocturne" cella affiche les sortie ou la valeur nocturne vaut 1 en bdd et pareil pour "sport"

    par contre si je veux afficher les 2 type de sortie donc "nocturne" et "sport" alors cela ne marche pas,

    Mon code en est la raison puisque la requete demande a affiché si les deux type de sorties valent 1 , mais moi je cherche affiché que l'une ou valent 1 et je ne sais comment faire

    <?php
     	// setlocale(LC_TIME, "fr_FR", "French");
        session_start();
        include('include/conndb.php');
        include('include/variables.php');
    
        // Vérifications
        // ****
        // Si aucune ville de renseignée
        if(empty($_GET['ville'])) {
        	header('Location: index.php');
        }else{
        	$ville = ucfirst(strtolower($_GET['ville']));
        }
    
         // Pagination
                $page = (!empty($_GET['page']) ? (int)$_GET['page'] : 1);
                $limite = 24; // Nombre d'élément à afficha dans la page
                $debut = ($page - 1) * $limite;
    
    
        		// Requete principale
      			$sql = 'SELECT * FROM sorties INNER JOIN categorie_de_sortie ON sorties.sortie_id = categorie_de_sortie.sortie_id WHERE sortie_active = "1"  AND (ville = :ville'; 
        		$pos_ville = $bdd->prepare("SELECT lattitude, longitude, Nom_commune, slug_commune FROM villes_de_france WHERE slug_commune = :ville");
                $pos_ville->execute(['ville' => $ville]);
                $row = $pos_ville->fetch(PDO::FETCH_ASSOC);  
    
    
                
                            
                $latitude=$row['lattitude'];
                $longitude=$row['longitude'];
    
    
                // Filtre de Distance Renseigné
                if (!empty($_POST['distance'])) {
                   $_SESSION['rayon'] = $_POST['distance'];
                   $rayon = $_SESSION['rayon'];
                }
    
                // Si on renseigne une valeur kilométrique
                if (!empty($rayon) && ($rayon != '0')) { 
                $formule="(6366*acos(cos(radians($latitude))*cos(radians(`lattitude`))*cos(radians(`longitude`) -radians($longitude))+sin(radians($latitude))*sin(radians(`lattitude`))))"; 
                $proxi_ville="SELECT DISTINCT Nom_commune,$formule AS dist FROM villes_de_france WHERE $formule<='$rayon' ORDER by dist ASC";
                $proxi_ville = $bdd->prepare($proxi_ville);
                $proxi_ville->execute();
                $sql .= " OR ville IN ( SELECT DISTINCT Nom_commune FROM villes_de_france WHERE $formule<='$rayon' ) " ;
                }elseif (empty($_POST['distance'])){ 
                $rayon = '20';
                $formule="(6366*acos(cos(radians($latitude))*cos(radians(`lattitude`))*cos(radians(`longitude`) -radians($longitude))+sin(radians($latitude))*sin(radians(`lattitude`))))"; 
                $proxi_ville="SELECT DISTINCT Nom_commune,$formule AS dist FROM villes_de_france WHERE $formule<='$rayon' ORDER by dist ASC";
                $proxi_ville = $bdd->prepare($proxi_ville);
                $proxi_ville->execute();
                $sql .= " OR ville IN ( SELECT DISTINCT Nom_commune FROM villes_de_france WHERE $formule<='$rayon' ) " ;
                }
    
    
    
                 // Traitement SQL du formulaire
                if (isset($_POST)){
                		$check = NULL;
                    	$sql .= ')';
    
                    	
    	      	// AND Multiples Checkboxes
                if (isset($_POST['cat_sport'])) {
                    $sql .= ' AND cat_sport = 1';
                }
    
                // AND Multiples Checkboxes
                if (isset($_POST['cat_nocturne'])) {
                    $sql .= ' AND cat_nocturne = 1';
                }
    
    
                if (!empty($_POST['categorie_sport'])) {
                	$check =  'checked="checked"';
                }else{
                	NULL;
                }
    
            }
            
    
        //$sql .= " GROUP BY sortie_id" ;
        $sql .= " ORDER BY sortie_date ASC, ( ville = :ville ) DESC, ville ASC " ;
        $sql .= ' LIMIT :limite OFFSET :debut'; // Limitation à l'affichage des données
        $sql = $bdd->prepare($sql);
        $sql->bindParam(':ville', $ville, PDO::PARAM_STR);
        $sql->bindValue('debut', $debut, PDO::PARAM_INT);
        $sql->bindValue('limite', $limite, PDO::PARAM_INT);
        $sql->execute();
    
        $resultFoundRows = $bdd->query('SELECT found_rows()');
        $nombredElementsTotal = $resultFoundRows->fetchColumn();
        $nombreDePages = ceil($nombredElementsTotal / $limite);
    
        // DEBUG
        var_dump($sql);
        var_dump($_POST);
    
    
    ?>

    checkboxes:

    <ul>
    									<label class="container_check">Sport
    									<input type="checkbox" name="cat_sport" value="1" <?php echo $check;?>> <span class="checkmark"></span></li>
    								    </label>
    
    								   <label class="container_check">Nocturne
    									<input type="checkbox" name="cat_nocturne" value="1" <?php echo $check;?>><span class="checkmark"></span></li>
    								    </label>
    								</ul>
    								  




    • Partager sur Facebook
    • Partager sur Twitter
      15 octobre 2021 à 13:29:27

      IN n'est pas la solution si c'est pour plusieurs colonnes.

      > je cherche affiché que l'une ou valent 1

      L'une ou ? L'autre ? C'est un OR qu'il te faut, pas un AND ?

      if (isset($_POST['cat_sport']) || isset($_POST['cat_nocturne'])) {
          $subconds = [];
          if (isset($_POST['cat_sport'])) {
              $subconds[] = 'cat_sport = 1';
          }
          if (isset($_POST['cat_nocturne'])) {
              $subconds[] = 'cat_nocturne = 1';
          }
          $sql .= ' AND (' . implode(' OR ', $subconds) . ')';
      }
      

      ?

      Que l'on pourrait "simplifier" dans ce cas particulier par :

      if (isset($_POST['cat_sport']) || isset($_POST['cat_nocturne'])) {
          $colonnes = [];
          if (isset($_POST['cat_sport'])) {
              $colonnes[] = 'cat_sport';
          }
          if (isset($_POST['cat_nocturne'])) {
              $colonnes[] = 'cat_nocturne';
          }
          $sql .= ' AND 1 IN(' . implode(', ', $colonnes) . ')';
      }
      

      > $ville = ucfirst(strtolower($_GET['ville']));

      Attention, ni ucfirst ni strtolower ne sont compatibles avec UTF-8, gare aux surprises !

      Et plein de choses qui pourraient être refactorisées.

      PS : j'ai déjà vu un code fortement semblable ...

      EDIT : je pense aussi qu'il y a une injection SQL possible via $_POST['distance']/$rayon/$_SESSION['rayon'] !

      -
      Edité par julp 15 octobre 2021 à 14:04:19

      • Partager sur Facebook
      • Partager sur Twitter
        15 octobre 2021 à 14:19:45

        Je te remercie c'est exactement ce que je cherchais à faire.

        J'ai repris une petite partie de ce que tu m'a dit, mon système marche mais peut etre qu''il ya mieux ou plus simple à faire

        Le but étant que les check

          // Traitement SQL du formulaire
                    if (isset($_POST)){
                    		$check_sport = 'checked="checked"';
                    		$check_noc = 'checked="checked"';
                        	$sql .= ')';
        
                    // Gestion checkboxes
        	      	if (isset($_POST['cat_sport']) || isset($_POST['cat_nocturne'])) {
           				$colonnes = [];
          				  if (isset($_POST['cat_sport'])) {
              			  $colonnes[] = 'cat_sport';
              			  $check_sport = 'checked="checked"';
           				 }else{
           				 	$check_sport = NULL;
           				 }
            		if (isset($_POST['cat_nocturne'])) {
                		$colonnes[] = 'cat_nocturne';
                		$check_noc = 'checked="checked"';
            		}else{
           				 	$check_noc = NULL;
           				 }
            		$sql .= ' AND 1 IN(' . implode(', ', $colonnes) . ')';
        				}
        
                }
                


        boxes soit cochées à l'arrivé sur la page pusi après elon les choix à la soumission du form

        • Partager sur Facebook
        • Partager sur Twitter
          15 octobre 2021 à 15:20:02

          Le code pourrait être bien plus simple, je pense, si toutes les checkbox avaient le même nom et que tu jouais sur leur valeur (genre cat_sport passe du name au value) plutôt que d'avoir un nom différent pour chacune d'elles. Ca te permettrait d'itérer directement sur une unique variable plutôt que d'avoir à tester chacune d'elles. On peut tout de même en l'état faire un tableau des clés POST (avec un mapping sur la colonne ?) pour déjà réduire le code. Il y en a réellement combien de ces clés cat_* ?

          Par ailleurs, il y a peut être là une première erreur de modélisation : ces colonnes cat_* auraient pu/dû être une relation many to many (ie avoir une table catégories ? en plus et une pour faire la relation entre cette dernière et les villes ?)

          -
          Edité par julp 15 octobre 2021 à 18:06:39

          • Partager sur Facebook
          • Partager sur Twitter
            15 octobre 2021 à 17:58:46

            Je pense qu'il faut mettre ce sujet en rapport avec celui-ci.

            • Partager sur Facebook
            • Partager sur Twitter

            plusieurs IN pour plusieurs colonnes

            × 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