Construction requete SQL et select multiple
Résolu/Fermé
saudek
-
20 sept. 2008 à 01:08
kryoportail Messages postés 222 Date d'inscription dimanche 10 août 2008 Statut Membre Dernière intervention 22 mai 2014 - 22 sept. 2008 à 14:33
kryoportail Messages postés 222 Date d'inscription dimanche 10 août 2008 Statut Membre Dernière intervention 22 mai 2014 - 22 sept. 2008 à 14:33
A voir également:
- Construction requete SQL et select multiple
- Liste déroulante choix multiple excel - Guide
- Paris multiple 2/6 explication ✓ - Forum Loisirs / Divertissements
- Requête sql pix - Forum Python
- Ecran multiple pc - Guide
- Windows presse papier multiple - Guide
9 réponses
kryoportail
Messages postés
222
Date d'inscription
dimanche 10 août 2008
Statut
Membre
Dernière intervention
22 mai 2014
125
20 sept. 2008 à 21:35
20 sept. 2008 à 21:35
Re !
Sans vouloir être lourd... (tu fais ce que tu veux !)
Comme l'a précisé Olivier, certes c'est un gros problème de sécurité, mais aussi de fonctionnement....
Si l'utilisateur met une apostrophe dans un de tes champs, ton script se plantera inévitablement, puisque MySql ne pourra pas interprété ta requête...
Si ton problème et d'avoir des AND sauf pour le canton, tu peux modifier la première solution que j'ai énoncé en y ajoutant la tienne...
// On récupère les données
$aCantons = $_POST['canton'];
$sName=$_POST['nom'];
...
...
// On remplie le tableau en utilisant les données fournies
$aWheres = array();
if( is_array($aCantons) && count($aCantons) > 0 )
{
// Cette boucle est là pour 'protéger' les valeurs de champs dans la requête...
$aWhereCantons = array();
foreach( $aCantons as $sCanton )
{
$aWhereCantons[] = "`Canton`='" . mysql_real_escape_string($sCanton) . "'";
}
// On sélectionne tous les enregistrements pour lesquels le canton est dans la liste (plus lisible et peu être plus rapide que liste de 'OR' )...
$aWheres[] = '`Canton` IN (' . implode( ', ', $aWhereCantons) . ')';
}
if( strlen($sName) > 0 ) { $aWheres[] = "`Nom`='" . mysql_real_escape_string($sName) . "'"; }
...
...
// On génère la clause 'Where'
if( count($aWheres) > 0 ) { $sWheres = ' WHERE ' . implode( ' AND ', $aWheres ); } else { $sWheres = ''; }
// Et on forme la requête...
$SQL = 'select * FROM adherents' . $sWheres;
V'la cette fois çà devrait aller, si ta liste de canton renvoi bien un tableau !
Amicalement,
S@M...
http://kryoportail.ath.cx
Sans vouloir être lourd... (tu fais ce que tu veux !)
Comme l'a précisé Olivier, certes c'est un gros problème de sécurité, mais aussi de fonctionnement....
Si l'utilisateur met une apostrophe dans un de tes champs, ton script se plantera inévitablement, puisque MySql ne pourra pas interprété ta requête...
Si ton problème et d'avoir des AND sauf pour le canton, tu peux modifier la première solution que j'ai énoncé en y ajoutant la tienne...
// On récupère les données
$aCantons = $_POST['canton'];
$sName=$_POST['nom'];
...
...
// On remplie le tableau en utilisant les données fournies
$aWheres = array();
if( is_array($aCantons) && count($aCantons) > 0 )
{
// Cette boucle est là pour 'protéger' les valeurs de champs dans la requête...
$aWhereCantons = array();
foreach( $aCantons as $sCanton )
{
$aWhereCantons[] = "`Canton`='" . mysql_real_escape_string($sCanton) . "'";
}
// On sélectionne tous les enregistrements pour lesquels le canton est dans la liste (plus lisible et peu être plus rapide que liste de 'OR' )...
$aWheres[] = '`Canton` IN (' . implode( ', ', $aWhereCantons) . ')';
}
if( strlen($sName) > 0 ) { $aWheres[] = "`Nom`='" . mysql_real_escape_string($sName) . "'"; }
...
...
// On génère la clause 'Where'
if( count($aWheres) > 0 ) { $sWheres = ' WHERE ' . implode( ' AND ', $aWheres ); } else { $sWheres = ''; }
// Et on forme la requête...
$SQL = 'select * FROM adherents' . $sWheres;
V'la cette fois çà devrait aller, si ta liste de canton renvoi bien un tableau !
Amicalement,
S@M...
http://kryoportail.ath.cx
kryoportail
Messages postés
222
Date d'inscription
dimanche 10 août 2008
Statut
Membre
Dernière intervention
22 mai 2014
125
22 sept. 2008 à 14:33
22 sept. 2008 à 14:33
Re,
Argh ! Oui c'est exacte... Bien joué !
Amicalement,
S@M...
http://kryoportail.ath.cx
Argh ! Oui c'est exacte... Bien joué !
Amicalement,
S@M...
http://kryoportail.ath.cx
Si j'ai bien compris tu voudrais que le contenu d'un select dépende du remplissement d'un des champs du formulaire ?
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
et bien le formulaire sert de filtre à l'affichage des adhérents. En méthode $_POST, le formulaire va donner des valeurs aux variables déclarées en haut du script ci dessus. Si, dans le formulaire, un champs n'est pas selectionné, il ne renvoie rien. S'il ne renvoie rien, on ne complète pas la requete de base, dans le cas contraire on complète la requete ($query). La ligne ci dessous illustre cette explication.
if ($POJP!='') {
$query .=' AND `POJP`="'.$POJP.'"'; }
La ou il faut se concentrer, c'est sur cette ligne :
if (is_array($canton))
foreach ($canton as $valeur)
{
if ($valeur !='') {
$query .=' AND `Canton`="'.$valeur.'"';
$canton2=''.$valeur.'';
}
Le problème avec le code ci dessus, c'est que dans mon select multiple, lorsque plusieurs champs sont selectionnés, la requete est complétée comme cela par exemple :
$query="select * FROM adherents WHERE 1=1 AND `canton`="blabla" AND `canton`="bloublou"";
Or moi je veux pas des AND entre les différentes valeurs de $canton, je veux des OR, mais tout en gardant les AND à la suite venant des autres champs (s'ils sont renseignés dans le form)
if ($POJP!='') {
$query .=' AND `POJP`="'.$POJP.'"'; }
La ou il faut se concentrer, c'est sur cette ligne :
if (is_array($canton))
foreach ($canton as $valeur)
{
if ($valeur !='') {
$query .=' AND `Canton`="'.$valeur.'"';
$canton2=''.$valeur.'';
}
Le problème avec le code ci dessus, c'est que dans mon select multiple, lorsque plusieurs champs sont selectionnés, la requete est complétée comme cela par exemple :
$query="select * FROM adherents WHERE 1=1 AND `canton`="blabla" AND `canton`="bloublou"";
Or moi je veux pas des AND entre les différentes valeurs de $canton, je veux des OR, mais tout en gardant les AND à la suite venant des autres champs (s'ils sont renseignés dans le form)
Quelques remarques :
Tu ne devrais pas avoir une suite de AND canton car seul le choix réalisé dans le select passe en valeur lors de la validation du formulaire.
Pour le nettoyage des cariables potées, comme décrit plus haut, il est impératif, au delà même d'une utilisation détournée, une faute de frappe de l'utilisateur peut entraîner un beug gênant.
Donc je dirais, à moins de n'avoir pas bien saisi le principe, qu'il faut réalisée une requête si le formulaire contient au moins un champs renseigné (le count du post précédent) executer la requête en complilant une suite de AND pour avoir les enregistrement répondant à tout les critères à la fois, ou une suite de or pour avoir les enregistrements contenant au moins un des critères. Pour ton cas il semble que tu recherches une suite de AND.
Il faudrait un message d'erreur élégant formulé en cas ou l'union des critères soit un ensemble vide.
Cordialement.
Tu ne devrais pas avoir une suite de AND canton car seul le choix réalisé dans le select passe en valeur lors de la validation du formulaire.
Pour le nettoyage des cariables potées, comme décrit plus haut, il est impératif, au delà même d'une utilisation détournée, une faute de frappe de l'utilisateur peut entraîner un beug gênant.
Donc je dirais, à moins de n'avoir pas bien saisi le principe, qu'il faut réalisée une requête si le formulaire contient au moins un champs renseigné (le count du post précédent) executer la requête en complilant une suite de AND pour avoir les enregistrement répondant à tout les critères à la fois, ou une suite de or pour avoir les enregistrements contenant au moins un des critères. Pour ton cas il semble que tu recherches une suite de AND.
Il faudrait un message d'erreur élégant formulé en cas ou l'union des critères soit un ensemble vide.
Cordialement.
Merci ça fonctionne comme je veux!!
Permettez moi, cependant de modifier ceci :
$aWhereCantons[] = "`Canton`='" . mysql_real_escape_string($sCanton) . "'";
En
$aWhereCantons[] = "'" . mysql_real_escape_string($sCanton) . "'";
Sinon j'avais `canton`="quelque chose" dans la parenthèse du IN.
Merci beaucoup.
Permettez moi, cependant de modifier ceci :
$aWhereCantons[] = "`Canton`='" . mysql_real_escape_string($sCanton) . "'";
En
$aWhereCantons[] = "'" . mysql_real_escape_string($sCanton) . "'";
Sinon j'avais `canton`="quelque chose" dans la parenthèse du IN.
Merci beaucoup.
kryoportail
Messages postés
222
Date d'inscription
dimanche 10 août 2008
Statut
Membre
Dernière intervention
22 mai 2014
125
20 sept. 2008 à 05:06
20 sept. 2008 à 05:06
Bonjour,
J'ai pas tout lu, mais ce que je peux dire, dans le cas qui est le tien, c'est que j'utilise cette méthode peut être effectivement plus propre ! :
// On récupère les données
$sCanton = $_POST['canton'];
$sName=$_POST['nom'];
...
...
// On remplie le tableau en utilisant les données fournies
$aWheres = array();
if( strlen($sCanton) > 0 ) { $aWheres[] = "`Canton`='" . mysql_real_escape_string($sCanton) . "'"; }
if( strlen($sName) > 0 ) { $aWheres[] = "`Nom`='" . mysql_real_escape_string($sName) . "'"; }
...
...
// On génère la clause 'Where'
if( count($aWheres) > 0 ) { $sWheres = ' WHERE ' . implode( ' OR ', $aWheres ); } else { $sWheres = ''; }
// Et on forme la requête...
$SQL = 'select * FROM adherents' . $sWheres;
Note : Ne pas oublier ques $_POST vient de l'utilisateur donc :
- Il est mieux de filtrer les données avant utilisation (par exemple en utilisant l'extension 'Filter' disponible à partir de PHP 5.2). Cf : https://www.php.net/manual/fr/intro.filter.php
- Il est primordial d'échapper les données afin d'éviter les injections SQL !!! via mysql_real_escape_string... Cf : https://www.php.net/manual/fr/function.mysql-real-escape-string.php
Image qu'un petit malin vienne rajouter dans la variable 'canton' qui est postée, des apostrophes.... Ta requête ne voudras plus rien dire, mais pire, si la variable 'canton' est bien choisie, elle peut permettre d'exécuter du code malicieux, genre un DELETE `adherents` ou un TRUNCATE `adherents`, voir un DROP `madatabase`... Bref, oui..., c'est dangereux !
Amicalement,
S@M...
http://kryoportail.ath.cx
J'ai pas tout lu, mais ce que je peux dire, dans le cas qui est le tien, c'est que j'utilise cette méthode peut être effectivement plus propre ! :
// On récupère les données
$sCanton = $_POST['canton'];
$sName=$_POST['nom'];
...
...
// On remplie le tableau en utilisant les données fournies
$aWheres = array();
if( strlen($sCanton) > 0 ) { $aWheres[] = "`Canton`='" . mysql_real_escape_string($sCanton) . "'"; }
if( strlen($sName) > 0 ) { $aWheres[] = "`Nom`='" . mysql_real_escape_string($sName) . "'"; }
...
...
// On génère la clause 'Where'
if( count($aWheres) > 0 ) { $sWheres = ' WHERE ' . implode( ' OR ', $aWheres ); } else { $sWheres = ''; }
// Et on forme la requête...
$SQL = 'select * FROM adherents' . $sWheres;
Note : Ne pas oublier ques $_POST vient de l'utilisateur donc :
- Il est mieux de filtrer les données avant utilisation (par exemple en utilisant l'extension 'Filter' disponible à partir de PHP 5.2). Cf : https://www.php.net/manual/fr/intro.filter.php
- Il est primordial d'échapper les données afin d'éviter les injections SQL !!! via mysql_real_escape_string... Cf : https://www.php.net/manual/fr/function.mysql-real-escape-string.php
Image qu'un petit malin vienne rajouter dans la variable 'canton' qui est postée, des apostrophes.... Ta requête ne voudras plus rien dire, mais pire, si la variable 'canton' est bien choisie, elle peut permettre d'exécuter du code malicieux, genre un DELETE `adherents` ou un TRUNCATE `adherents`, voir un DROP `madatabase`... Bref, oui..., c'est dangereux !
Amicalement,
S@M...
http://kryoportail.ath.cx
Alors je reprécise,
Le formulaire est une suite de select (6) à part 1 input text pour chercher un nom en générant la close LIKE dans la requete.
Pour les problèmes de sécurité, pas de soucis le dossier est en accès restreint, protégé par htaccess. Donc je vais pas me compléter la vie avec ça. Mias ls conseils à ce sujet sont les bienvenue merci.
Ce que je recherche, c'est insérer des OR entre les différentes valeurs de cantons tirées du array PUIS des AND pour tous les autres champs renseignés.
C'est là la difficulté, pouvoir insérer des AND et des OR dans la même requête. Donc le script gentillement donné par kryoportail ne correspond pas à ce que je veux.
Est ce que je peux utiliser la fonction implode JUSTE pour la variabe canton?
Parce que j'ai essayé de mettre OR avant canton, mais 1=1 OR quelque chose...
Je vous précise que TOUT marche, que tous les champs du formulaires s'ajoutent bien dans la requete avec des AND sauf que le select multiple génère des AND aussi avec le script que j'ai, et moi je veux des OR entre les cantons.
Le formulaire est une suite de select (6) à part 1 input text pour chercher un nom en générant la close LIKE dans la requete.
Pour les problèmes de sécurité, pas de soucis le dossier est en accès restreint, protégé par htaccess. Donc je vais pas me compléter la vie avec ça. Mias ls conseils à ce sujet sont les bienvenue merci.
Ce que je recherche, c'est insérer des OR entre les différentes valeurs de cantons tirées du array PUIS des AND pour tous les autres champs renseignés.
C'est là la difficulté, pouvoir insérer des AND et des OR dans la même requête. Donc le script gentillement donné par kryoportail ne correspond pas à ce que je veux.
Est ce que je peux utiliser la fonction implode JUSTE pour la variabe canton?
Parce que j'ai essayé de mettre OR avant canton, mais 1=1 OR quelque chose...
Je vous précise que TOUT marche, que tous les champs du formulaires s'ajoutent bien dans la requete avec des AND sauf que le select multiple génère des AND aussi avec le script que j'ai, et moi je veux des OR entre les cantons.