champ vide moteur de recherche

r7expert
Invité n'ayant pas de compte PHPfrance

19 août 2014, 11:57

Bonjour,

Je crée un petit moteur de recherche avec filtre tout simple mon souci c'est que dans le filtre si j'ai aucune valeur (j'ai essayé de mettre un champ vide) il le compte quand même donc il effectue une recherche sur un paramètre vide. Comment je peux faire une recherche sans prendre en compte le paramètre vide.

exemple : je voudrais tous les jeux de ma base mais sans le filtre "console"
<p>Vous recherchez quel jeu ?</p>
	<input type="text" name="jeu" />
	</br>
	</br>
	
	<p>La console ?</p>
	<select name="choix">
	<option value=""></option>
    <option value="NES">NES</option>
    <option value="Megadrive">Megadrive</option>
    <option value="Nintendo 64">Nintendo 64</option>
$requete = htmlspecialchars($_POST['jeu']); 
$choix = ($_POST['choix']);
$query = mysql_query("SELECT * FROM jeux_video WHERE nom LIKE '%$requete%' AND console = '$choix' ORDER BY nom ASC") or die (mysql_error());
Merci

Eléphant du PHP | 113 Messages

19 août 2014, 12:26

Ton problème vient de là : "AND console = '$choix'"

Il faudrait que tu le fasse de cette manière:
//Si le choix n'est pas vide
if (!empty($_POST['choix'])) {
   $choix = "AND console = '" . htmlentities($_POST['choix']) . "'";
}


ynx
Mammouth du PHP | 586 Messages

19 août 2014, 12:36

Salut,

Voici une solution possible :
// requête par défaut (sans filtres)
$maRequete = 'SELECT * FROM jeux_video ORDER BY nom ASC';

if (!empty($_POST['jeu']) && !empty($_POST['choix'])) { // si l'utilisateur a choisi 2 filtres
	$maRequete = "SELECT * FROM jeux_video WHERE nom LIKE '%" . mysql_real_escape_string($_POST['jeu']) . "%' AND console = '" . mysql_real_escape_string($_POST['choix']) . "' ORDER BY nom ASC";
} else if (!empty($_POST['jeu'])) { // si l'utilisateur a choisi que le filtre jeu
	$maRequete = "SELECT * FROM jeux_video WHERE nom LIKE '%" . mysql_real_escape_string($_POST['jeu']) . "%' ORDER BY nom ASC";
} else if (!empty($_POST['choix'])) { // si l'utilisateur a choisi que le filtre console
	$maRequete = "SELECT * FROM jeux_video WHERE console = '" . mysql_real_escape_string($_POST['choix']) . "' ORDER BY nom ASC";
}

$query = mysql_query($maRequete) or die (mysql_error());
On pourrait factoriser davantage la requête mais cela demande plus de condition lors de la construction de la requête (en fonction des filtres activés ou non). Pour seulement deux filtres, cet exemple reste assez simple.

Important : htmlspecialchars ou htmlentities ne protège pas les données contre les injections sql. Comme leurs noms l'indique, ces fonctions doivent être utilisés pour afficher les données en HTML.
Pour contrer les injections sql avec l'api Mysql, il faut utiliser la fonction mysql_real_escape_string.

Bonne journée

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

19 août 2014, 16:16

Pour ma part je construirais la requête dynamiquement :
$requete = isSet($_POST['jeu']) ? htmlspecialchars($_POST['jeu']) : ''; 
$choix = isSet($_POST['choix']) ? $_POST['choix'] : '';

$conditions = array();
if ($requete!='')
   $condition[] = "nom LIKE '%$requete%' "
if ($choix!='')
   $condition[] = "console = '$choix' "

$sql = "SELECT * FROM jeux_video ";
if (count($cond) > 0)
   $sql.= " WHERE " . implode(' AND ', $cond);
$sql.= " ORDER BY nom ASC ";

$query = mysql_query($sql) or die (mysql_error());
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

r7expert
Invité n'ayant pas de compte PHPfrance

19 août 2014, 16:55

Merci pour vos réponses.

Pour la 1ère solution je comprends bien le principe mais je tombe devant un autre problème c'est que en rajoutant le "AND console = '" . htmlentities($_POST['choix']) . "'" je me retrouve avec une requête comme celle-ci :
"SELECT * FROM jeux_video WHERE nom LIKE '%$requete%' AND console = AND console = '" . htmlentities($_POST['choix']) . "' ORDER BY nom ASC"
cela fait doublons, remplacer le $choix par un morceaux de la requête SQL m’emmène à une erreur.

Pour la seconde solution sa fonctionne mais avec d'autres conditions on y perd vite la tête ;)

Je ne connais le principe des requêtes dynamiques et je m'y colle tout de suite pour voir ce que sa donne merci.

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

20 août 2014, 21:32

En fait, la requête SQL n'est rien d'autres qu'une chaine de caractères que php va transmettre à la base de données pour qu'elle l’interprète. L'idée est donc de construire cette chaine de caractère de façon dynamique en concaténant les morceaux de chaine dont tu as besoin.

Cela reviendrait donc à découper la requête ainsi :
$sql = "SELECT * FROM jeux_video WHERE " . " nom LIKE '%$requete%' " . " AND console = '$choix' " . " ORDER BY nom ASC ";
$sql = "SELECT * FROM jeux_video WHERE ";
$sql.= " nom LIKE '%$requete%' ";
$sql.= " AND console = '$choix' ";
$sql.= " ORDER BY nom ASC ";
et mettre des conditions sur les morceaux à intercaler
$sql = "SELECT * FROM jeux_video WHERE 1=1 ";
if ($requete!='')
   $sql.= " AND nom LIKE '%$requete%' ";
if ($choix!='')
   $sql.= " AND console = '$choix' ";
$sql.= " ORDER BY nom ASC ";
le code précédent fait la même chose, mais à l'avantage de gérer un peu plus proprement l'insertion des WHERE et AND en fonction des conditions déjà présentes dans la requête (sans utiliser l'astuce du un 1=1 pour pas se prendre la tête à savoir s'il faut mettre un WHERE ou un AND avant la condition) :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 113 Messages

20 août 2014, 23:48

r7expert, je pensais que tu aurais compris qu'il n'y aurais plus eu beoin du AND console = dans ta requête puisque tu le rajoutes après seulement si ton POST est plein #-o

Petit nouveau ! | 2 Messages

21 août 2014, 10:30

En fait, la requête SQL n'est rien d'autres qu'une chaine de caractères que php va transmettre à la base de données pour qu'elle l’interprète. L'idée est donc de construire cette chaine de caractère de façon dynamique en concaténant les morceaux de chaine dont tu as besoin.

Cela reviendrait donc à découper la requête ainsi :
$sql = "SELECT * FROM jeux_video WHERE " . " nom LIKE '%$requete%' " . " AND console = '$choix' " . " ORDER BY nom ASC ";
$sql = "SELECT * FROM jeux_video WHERE ";
$sql.= " nom LIKE '%$requete%' ";
$sql.= " AND console = '$choix' ";
$sql.= " ORDER BY nom ASC ";
et mettre des conditions sur les morceaux à intercaler
$sql = "SELECT * FROM jeux_video WHERE 1=1 ";
if ($requete!='')
   $sql.= " AND nom LIKE '%$requete%' ";
if ($choix!='')
   $sql.= " AND console = '$choix' ";
$sql.= " ORDER BY nom ASC ";
le code précédent fait la même chose, mais à l'avantage de gérer un peu plus proprement l'insertion des WHERE et AND en fonction des conditions déjà présentes dans la requête (sans utiliser l'astuce du un 1=1 pour pas se prendre la tête à savoir s'il faut mettre un WHERE ou un AND avant la condition) :)
oh la la,il est obligé d'avouer que le grand maître vit parmi le peuple!! =D> =D>