Ajouter une requete seconde à une principale

Mammouth du PHP | 643 Messages

30 août 2019, 11:55

Salut tout le monde.
Bon je deviens dingue en fait j'ai fait mes requetes tout marche nickel.
Maintenant j'aimerais que ma 2 requete complete la principal si une distance est selectionné

En gros: si distance est renseignée alors j'applique ma requete proxi_ville à ma requete sql
// Traitement de la pagination
	$page = (!empty($_GET['page']) ? (int)$_GET['page'] : 1);
	$limite = 10; // Nombre d'élément à afficha dans la page
	$debut = ($page - 1) * $limite;
	
	// Requetes bars selon option
	$sql = 'SELECT SQL_CALC_FOUND_ROWS * FROM bars WHERE ville = :ville';      
    $sql .= ' LIMIT :limite OFFSET :debut'; // limite à 5
    $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();
	
	
	// Récupération des données selon la ville de renseignée
	$pos_ville = $bdd->prepare("SELECT lattitude, longitude  FROM villes_de_france WHERE Nom_commune = '$ville'");
	$pos_ville->execute();
	$row = $pos_ville->fetch(PDO::FETCH_ASSOC);
								
	$latitude=$row['lattitude'];
	$longitude=$row['longitude'];
	
	// Si on applique une distance de filtre
	if (!empty($_POST['distance'])) {
		$rayon = $_POST['distance'];
	}else{
		$rayon = NULL;
	}
	//echo $rayon;
	
	// Formule + select des villes selon la distance
	$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();
   	if($proxi_ville->rowCount() > 1) {	
					while($result = $proxi_ville->fetch(PDO::FETCH_ASSOC)){  
						echo $result['Nom_commune'].'<br>'; // toutes les villes selon la distance choisie
					}
   	}

	
	// Calcul de la pagination
	$resultFoundRows = $bdd->query('SELECT found_rows()');
	$nombredElementsTotal = $resultFoundRows->fetchColumn();
	$nombreDePages = ceil($nombredElementsTotal / $limite);
	//var_dump($sql);

Mammouth du PHP | 643 Messages

30 août 2019, 16:06

J'ai avancer ça marche, si je rajoute une ville au pif
Mais mon résultat me renvoi plusieurs villes forcément.

Du coup comment y rajouter dans ma requete svp
// Traitement de la pagination
	$page = (!empty($_GET['page']) ? (int)$_GET['page'] : 1);
	$limite = 10; // Nombre d'élément à afficha dans la page
	$debut = ($page - 1) * $limite;
	
	// Requetes Pincipale
	$sql = 'SELECT SQL_CALC_FOUND_ROWS * FROM bars WHERE ville = :ville';      
    
	
	// Récupération des données selon la ville de renseignée
	$pos_ville = $bdd->prepare("SELECT lattitude, longitude  FROM villes_de_france WHERE Nom_commune = '$ville'");
	$pos_ville->execute();
	$row = $pos_ville->fetch(PDO::FETCH_ASSOC);						
	$latitude=$row['lattitude'];
	$longitude=$row['longitude'];
	
	// Si on applique une distance de filtre
	if (!empty($_POST['distance'])) {
		$rayon = $_POST['distance'];
	

	// Formule + select des villes selon la distance
	$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();
   	if($proxi_ville->rowCount() > 0) {	
					while($result = $proxi_ville->fetch(PDO::FETCH_ASSOC)){  
						$ville_secondaire = $result['Nom_commune'];
						echo $result['Nom_commune'].'<br>';
					}
   	}

	$sql .= " OR ville = 'echirolles' " ; // Si une distance est renseignée on rajoute les villes de la zone dans la requete
		}else{
		$rayon = NULL; // Le champ de recherche kilometrique est vide
	}
	
	$sql .= ' LIMIT :limite OFFSET :debut'; // limite à 5
    $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();
	
	
	// Calcul de la pagination
	$resultFoundRows = $bdd->query('SELECT found_rows()');
	$nombredElementsTotal = $resultFoundRows->fetchColumn();
	$nombreDePages = ceil($nombredElementsTotal / $limite);
	var_dump($sql);
La partie directement concernée est celle ci:
J'ai mis en exemple mais bien sur je cherche à mettre les valeurs de $ville_secondaire
if($proxi_ville->rowCount() > 0) {	
					while($result = $proxi_ville->fetch(PDO::FETCH_ASSOC)){  
						$ville_secondaire = $result['Nom_commune'];
						echo $result['Nom_commune'].'<br>';
					}
   	}

	$sql .= " OR ville IN ( 'fontaine', 'echirolles' ) " ; // Si une distance est renseignée on rajoute les villes de la zone dans la requete
	//$sql .= " OR ville = 'echirolles' OR ville = 'fontaine' " ; // Si une distance est renseignée on rajoute les villes de la zone dans la requete version OR
		}else{
		$rayon = NULL; // Le champ de recherche kilometrique est vide
	}

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10467 Messages

30 août 2019, 17:04

Hello !

Pas certain d'avoir tout compris... en gros, ta seconde requête te retourne une liste de nom de communes que tu veux utiliser pour compléter un critère de ta requête principal ?

Solution simple mais pas élégante et pas optimisée :
if ($proxi_ville->rowCount() > 0) {	
  while($result = $proxi_ville->fetch(PDO::FETCH_ASSOC)){  
    $sql .= " OR ville = '" .  $result['Nom_commune'] . "' "; // attention toutefois aux noms de communes qui auraient des apostrophes dans leurs noms
  }
}
Solution simple un poil plus élégante mais toujours pas optimisée :
$communes = array();
 if($proxi_ville->rowCount() > 0) {	
  while($result = $proxi_ville->fetch(PDO::FETCH_ASSOC)){  
    $communes[] = "'" .  $result['Nom_commune'] . "'"; // toujours le même problème avec les apostrophes
  }
}
if (!empty($commune))
      $sql .= " OR ville IN ( " .  implode(',', $communes) . " ) " ;
La meilleure solution consiste probablement à ne faire qu'une seule requête avec une sous requête (et donc ne pas exécuter la seconde requête en php, mais inclure celle-ci directement dans un IN de ta requête principale pour n'avoir qu'une requête à exécuter). Quelque chose du genre :
$sql = 'SELECT SQL_CALC_FOUND_ROWS * FROM bars WHERE ville = :ville';   
$sql .= " OR ville IN ( SELECT DISTINCT Nom_commune FROM villes_de_france WHERE $formule<='$rayon' ) " ;
A adapter en fonction de ton besoin :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Mammouth du PHP | 643 Messages

30 août 2019, 18:02

C'est cool j'ai opté pour la 3ème proposition et c'est nikel, merci à toi.
Par contre effectivement tellement je susi dessus je n'y avais pas pensé mail pour les viles qui ont un apostrophe quel est la meilleure solution ?

En cas le code appliqué je l'ai mis dans le cas si le filtre distance est renseigné:
// Requetes Pincipale
	$sql = 'SELECT SQL_CALC_FOUND_ROWS * FROM bars WHERE ville = :ville';      
    
	
	// Récupération des données selon la ville de renseignée
	$pos_ville = $bdd->prepare("SELECT lattitude, longitude  FROM villes_de_france WHERE Nom_commune = '$ville'");
	$pos_ville->execute();
	$row = $pos_ville->fetch(PDO::FETCH_ASSOC);						
	$latitude=$row['lattitude'];
	$longitude=$row['longitude'];
	
	// Si on applique une distance de filtre
	if (!empty($_POST['distance'])) {
		$rayon = $_POST['distance'];
	

	// Formule GPS
	$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();
   	if($proxi_ville->rowCount() > 0) {	
		// Debug Nom des villes selon le filte de la distance
		while($result = $proxi_ville->fetch(PDO::FETCH_ASSOC)){  
			var_dump($result['Nom_commune']);
		}
   	}

		// On ajoute les villes selon la zone kilomètrique
		$sql .= " OR ville IN ( SELECT DISTINCT Nom_commune FROM villes_de_france WHERE $formule<='$rayon' ) " ;
		}else{
		$rayon = NULL; // Le champ de recherche kilometrique est vide
	}
	
	$sql .= ' LIMIT :limite OFFSET :debut'; // limite à 5
    $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();
PS: la valeur selectionné dans le <select> pour les km de reste pas affiché une fois la page rechargé et je ne vois pas pourquoi :/

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10467 Messages

02 sept. 2019, 11:32

L'un des avantages de la 3e solution et de la sous-requête est que tu n'as pas à te soucier des apostrophes dans le nom des villes. En effet, la base va comparer des valeurs qui sont déjà stockées et tu n'as donc pas/plus à "préparer" celles-ci pour pouvoir les utiliser dans une requête :)

Pour ton select qui n'affiche plus la valeur sélectionnée avant l'envoi du formulaire, c'est à toi de dire que tu veux sélectionner celle-ci par défaut une fois la page rechargée. Il te faut donc vérifier si ta variable $_POST['distance'] est bien définie (pour savoir si le formulaire a été envoyé ou non) et si elle est présente, il faut ajouter l'attribut "selected" dans la balise <option> correspondante de ton select. Si ça n'est pas clair, je te suggère d'ouvrir un autre sujet et de mettre le code de ton <select> pour qu'on puisse te guider plus facilement :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Mammouth du PHP | 1341 Messages

02 sept. 2019, 17:14

si l'on trie http://www.monbeauvillage.fr/saint par nom de commune, on se rend compte qu'il y a 5 Saint-Agnan en France, 6 Saint-Aignan ... alors se baser sur le nom d'une commune pour trouver les communes proches, c'est aléatoire.