[Resolu] Recherche multi critères

Recherche multi critères [Resolu] - PHP - Programmation

Marsh Posté le 18-06-2012 à 15:16:56    

Bonjour,
 
Je bloque actuellement sur la manière de coder mon moteur de recherche sur mon site.
Je fais une vérification sur chaque critère pour voir s'ils possèdent une valeur auquel cas je les ajoute dans un tableau qui les régroupera toute en ayant déjà la forme prête pour la futur requête SQL.
 
Puis gràce à une boucle, je rajoute les AND de ma requête.
 
Grâce au compteur utilisé auparavant pour le tableau, je verifie s'il y a eu au moins un critère et je lance la requete avec le WHERE regroupant toutes les critères.
 
Voilà l'adresse du site pour vous faire une idée.
 
http://hightechservices.free.fr/ordinateur.php
 
Lors de n'importe quelle recherche, je retrouve toujours le seul est unique enregistrement contenu dans la table Ordinateur de ma base de données.
 
Avez-vous une idée sur ce qui ne va pas?
 
D'avance merci.


Message édité par fmdcc le 19-06-2012 à 11:39:23
Reply

Marsh Posté le 18-06-2012 à 15:16:56   

Reply

Marsh Posté le 18-06-2012 à 15:45:50    

1) fais un echo de ta requête SQL pour voir ce qu'elle fait.
 
2) dans ton moteur de recherche, ça serait bien de réafficher les paramètres saisis correspondant au résultat de la requête ;)
 
Edit : dans mon logiciel de help-desk ASTRES (cf ma signature), j'ai codé pleins de moteurs de recherche de ce type. Tu peux regarder comment j'ai fait ;)


Message édité par rufo le 18-06-2012 à 15:46:48

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 18-06-2012 à 15:53:23    

Tes 2 remarques sont bonnes et je vais déjà les appliquer et voir ce que ça donne.
 
Je jeterai également un oeil sur ce logiciel.
 
Merci pour ton aide.


Message édité par fmdcc le 18-06-2012 à 16:04:50
Reply

Marsh Posté le 18-06-2012 à 17:35:18    

Je n'y suis toujours pas parvenu.
 
Voilà un aperçu de mon code avec tout d'abord le formulaire puis le traitement php.
 

Code :
  1. <form name="RechercheOrdinateur" action="rechercheOrdinateur.php" method="POST" onSubmit="return checkForm();">
  2.        
  3.     <h4>Critères de recherche</h4>
  4.     <table border="0">
  5.  <tr>
  6.   <td>Processeur :</td>
  7.             <td><SELECT name="lst_processeur" style="width:12em">
  8.    <OPTION VALUE=null></OPTION>
  9.    <OPTION VALUE="coreI3">Intel Core i3</OPTION>
  10.    <OPTION VALUE="coreI5">Intel Core i5</OPTION>
  11.    <OPTION VALUE="coreI7">Intel Core i7</OPTION>
  12.                 <OPTION VALUE="amdPhenom">AMD Phenom</OPTION>
  13.                 <OPTION VALUE="amdFusion">AMM Fusion</OPTION>
  14.    </SELECT></td>
  15.  </tr>
  16. ...
  17. <p align=center>
  18. <input type=submit value="Rechercher">
  19. </p>


 

Code :
  1. <?
  2.   // connexion
  3.   include('secure/config.php');
  4.   pg_connect("host=$SQLhost user=$SQLlogin password=$SQLpass dbname=$SQLdbname" )
  5.   or die("Impossible de se connecter" );
  6.   // on récupère les critères sélectionnés
  7.             //extract($_POST);
  8.   $lst_processeur = $_POST["lst_processeur"];
  9.             $i = 0;
  10.          
  11.             // si la variable est présente, on lui affecte une place dans le tableau 'choix[]', qui nous servira ensuite à construire le WHERE de la requête.
  12.             if(!empty($lst_processeur)) { $choix[$i++] = "processeur = '$lst_processeur'"; }
  13.             if(!empty($lst_hdd)) { $choix[$i++] = "hdd = '$lst_hdd'"; }
  14.             if(!empty($lst_ram)) { $choix[$i++] = "ram = '$lst_ram'"; }
  15.             if(!empty($lst_cg)) { $choix[$i++] = "cg = '$lst_cg'"; }
  16.             if(!empty($lst_ecran)) { $choix[$i++] = "cg = '$lst_ecran'"; }
  17.             // on insère les éléments remplis dans une variable $critere, en commençant par la première occurrence, puis on boucle
  18.             $critere = $choix[0]." ";
  19.          
  20.             for($j=1;$j<$i;$j++)
  21.             {
  22.                 $critere .= " AND ".$choix[$j]." ";
  23.             }
  24.             // enfin on fait la requête si $i >0, ça veut dire qu'il y a des critères
  25.             if($i > 0)
  26.                 {
  27.                 // requete de selection
  28.    $query = "SELECT * FROM ordinateur WHERE $critere ORDER BY prix";
  29.                 }
  30.             // si $i = 0, alors l'utilisateur n'a pas saisi de critère, là soit on fait la même requete mais sans "WHERE $critere", soit on lui demande de saisir au moins un critère.
  31.             else
  32.                 {
  33.                 $query = "SELECT * FROM ordinateur ORDER BY prix";
  34.                 }
  35.   $result = pg_query($query);
  36.   pg_close();


Message édité par fmdcc le 19-06-2012 à 11:01:58
Reply

Marsh Posté le 18-06-2012 à 17:43:44    

<OPTION VALUE=null></OPTION>   -> déjà, ça, c'est pas bon, vaudrait mieux mettre <OPTION VALUE=""></OPTION>
 
Pour info, pas besoin de faire $choix[$i++] = "....";  
Tu peux faire direct : $choix[] = "...";
 
Pour savoir si t'as des critères, juste un if (!empty($choix)).
 
Et pour les and à ajouter entre les critères :  
$critere = implode(" and ", $choix);


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 18-06-2012 à 17:55:58    

Je vais mettre tout ça au point.
 
merci

Reply

Marsh Posté le 18-06-2012 à 18:05:54    

Le problème, c'est que dès le début, j'ai l'impression que mes critères sont toujours nuls
 

Code :
  1. <? echo $lst_processeur?>/<? echo $lst_hdd?>/<? echo $lst_ram?>/<? echo $lst_cg?>/<? echo $lst_ecran?>


 
J'ai ajouté cette ligne pour voir les critères demandé et rien n'en sors comme critère.
 
Pour la fonction implode avec les AND, j'ai ce message d'erreur malgré que ce soit les bons arguments.
Warning: implode() [function.implode]: Bad arguments.


Message édité par fmdcc le 18-06-2012 à 18:13:31
Reply

Marsh Posté le 19-06-2012 à 09:57:05    

T'as quoi quand tu fais print_r($_POST); ?
 
Cela dit, lignes 8 et 10 du script rechercheOrdinateur.php me paraissent louches :/


Message édité par rufo le 19-06-2012 à 09:58:14

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 19-06-2012 à 10:33:07    

Avec print_r($_POST);, j'obtiens bien les critères sélectionnés.
 
Si je choisis par exemple disque dur 320 Go, j'ai:
 
Array ( [Processeur] => [DisqueDur] => 320 [Ram] => [CG] => [ecran] => )  
 
Concernant les lignes 8 et 10, il s'agissait de test que j'avais oublié de supprimer.
 

Code :
  1. <?
  2.   // connexion
  3.   include('secure/config.php');
  4.   pg_connect("host=$SQLhost user=$SQLlogin password=$SQLpass dbname=$SQLdbname" )
  5.   or die("Impossible de se connecter" );
  6.   // on récupère les critères sélectionnés
  7.             extract($_POST);
  8.             $i = 0;
  9.          
  10.             // si la variable est présente, on lui affecte une place dans le tableau 'choix[]', qui nous servira ensuite à construire le WHERE de la requête.
  11.             if(!empty($lst_processeur)) { $choix[] = "processeur = '$lst_processeur'"; }
  12.             if(!empty($lst_hdd)) { $choix[] = "hdd = '$lst_hdd'"; }
  13.             if(!empty($lst_ram)) { $choix[] = "ram = '$lst_ram'"; }
  14.             if(!empty($lst_cg)) { $choix[] = "cg = '$lst_cg'"; }
  15.             if(!empty($lst_ecran)) { $choix[] = "cg = '$lst_ecran'"; }
  16.             // on insère les éléments remplis dans une variable $critere, en commençant par la première occurrence, puis on boucle
  17.             $critere = $choix[0]." ";
  18.          
  19.             for($j=1;$j<$i;$j++)
  20.             {
  21.                 $critere .= " AND ".$choix[$j]." ";
  22.             }
  23.   // $critere = implode(" and ", $choix);
  24.             // enfin on fait la requête si $i >0, ça veut dire qu'il y a des critères
  25.             if($i > 0)
  26.                 {
  27.                 // requete de selection
  28.    $query = "SELECT * FROM ordinateur WHERE $critere ORDER BY prix";
  29.                 }
  30.             // si $i = 0, alors l'utilisateur n'a pas saisi de critère, là soit on fait la même requete mais sans "WHERE $critere", soit on lui demande de saisir au moins un critère.
  31.             else
  32.                 {
  33.                 $query = "SELECT * FROM ordinateur ORDER BY prix";
  34.                 }
  35.   print_r($_POST);
  36.   $result = pg_query($query);
  37.   pg_close();
  38.   while($ligne = pg_fetch_array($result)){
  39.   ?>


Message édité par fmdcc le 19-06-2012 à 10:35:44
Reply

Marsh Posté le 19-06-2012 à 11:31:52    

Problème résolu.
 
Tout d'abord dans mon code sur le formulaire, je faisais une grosse confusion entre l'attribut name et id et je fais appelle au nom donné dans l'id pour le sript php avec POST...
 
Rien ne pouvez en sortir donc. Ca m'a toujours rendu confu ces 2 attributs name et id.
 
Puis pour la condition qui commence en ligne 29, j'ai ajouté une incrémentation du compteur i pour chaque critère remplis.
 
Ce qui nous donne au final:
 

Code :
  1. <?
  2.   // connexion
  3.   include('secure/config.php');
  4.   pg_connect("host=$SQLhost user=$SQLlogin password=$SQLpass dbname=$SQLdbname" )
  5.   or die("Impossible de se connecter" );
  6.   // on récupère les critères sélectionnés
  7.             extract($_POST);
  8.             $i = 0;
  9.          
  10.             // si la variable est présente, on lui affecte une place dans le tableau 'choix[]', qui nous servira ensuite à construire le WHERE de la requête.
  11.             if(!empty($lst_processeur))
  12.    {
  13.    $choix[] = "processeur = '$lst_processeur'";
  14.    $i++;
  15.    }
  16.             if(!empty($lst_hdd))
  17.    {
  18.    $choix[] = "hdd = '$lst_hdd'";
  19.    $i++;
  20.    }
  21.             if(!empty($lst_ram))
  22.    {
  23.    $choix[] = "ram = '$lst_ram'";
  24.    $i++;
  25.    }
  26.             if(!empty($lst_cg))
  27.    {
  28.    $choix[] = "cg = '$lst_cg'";
  29.    $i++;
  30.    }
  31.             if(!empty($lst_ecran))
  32.    {
  33.    $choix[] = "ecran = '$lst_ecran'";
  34.    $i++;
  35.    }
  36.             // on insère les éléments remplis dans une variable $critere, en commençant par la première occurrence, puis on boucle
  37.   $critere = implode(" and ", $choix);
  38.             // enfin on fait la requête si $i >0, ça veut dire qu'il y a des critères
  39.             if($i > 0)
  40.                 {
  41.                 // requete de selection
  42.    $query = "SELECT * FROM ordinateur WHERE $critere ORDER BY prix";
  43.                 }
  44.             // si $i = 0, alors l'utilisateur n'a pas saisi de critère, là soit on fait la même requete mais sans "WHERE $critere", soit on lui demande de saisir au moins un critère.
  45.             else
  46.                 {
  47.                 $query = "SELECT * FROM ordinateur ORDER BY prix";
  48.                 }
  49.   print_r($_POST);
  50.   print_r($critere);
  51.   print_r($query);
  52.   $result = pg_query($query);
  53.   pg_close();
  54.   while($ligne = pg_fetch_array($result)){
  55.   ?>


 
Merci pour ton aide rufo.


Message édité par fmdcc le 19-06-2012 à 11:40:10
Reply

Marsh Posté le 19-06-2012 à 11:31:52   

Reply

Marsh Posté le 19-06-2012 à 11:43:41    

name => c'est le nom du champ dans le formulaire, récupéré côté serveur dans $_GET ou $_POST. Y'a que ds balise de formulaire qui peuvent avoir un name.
 
id => n'importe quelle balise peut avoir un id. Sert surtout pour le JS ( getElementById() ) ou le CSS.
 
Une balise peut avoir un name ET un id (et en plus, la valeur de ces 2 attributs peut être identique, mais c'est pas obligé).
 
Et pour info, pas de style dans le HTML (utilisation de l'attribut "style" dans le html à éviter au maximum -> utiliser css). Pareil, éviter le JS intrusif dans le html. JS uniquement dans des fichiers js.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 19-06-2012 à 11:43:47    

plop
tu peux commencer par envoyer un array associatif directement, ca t'evitera de galerer ensuite et c'est plus clean

Code :
  1. <select multiple id="criteriaProcessor" name="criteria[processor][]">
  2. <option value="">-</option>
  3. <option value="i5">i5</option>
  4. ...
  5. </select>
  6. <select id="criteriaRam" name="criteria[ram]">
  7. <option value="">-</option>
  8. <option value="4">4gb</option>
  9. ...
  10. </select>


 
ca te permet de recup directement un array $criteria
 

Code :
  1. // query de fallback. si pas de criteres elle sera lancée telle qu'elle
  2. $sqlquery = 'SELECT * FROM ordinateur WHERE 1 ';
  3. $criteria = (isset($_POST['criteria'])&&is_array($_POST['criteria']))?$_POST['criteria']:array();
  4. if (!empty($criteria)){
  5.     // pour chaque critere envoyé on recupere la key (ie: processor ou ram) et la value
  6.     foreach ($criteria as $key=>$value){
  7.         // si la value est un tableau ca veut dire qu'on a utilisé un select multiple d'ou la notation name='criteria[processor][]' en html
  8.         // la dans mon ex j'utilise un 'OR' pour chaque sous valeur
  9.         if (is_array($value)){
  10.             $sqlquery .= ' AND (
  11.             $subCount = 0;
  12.             foreach ($value as $subvalue){
  13.                 if($subcount){
  14.                     $sqlquery .= ' OR ';
  15.                 }
  16.                 $sqlquery .= '\''. $key .'\' = '. $subvalue ';
  17.                 $subCount++;
  18.             }
  19.             $sqlquery .= ')';
  20.         }else{
  21.             // si ce n'est pas un tableau c'est un critere 'simple'
  22.             $sqlquery .= ' AND \''. $key .'\' = '. $value ';
  23.         }
  24.     }
  25. }


 
code a l'arrache et pas testé mais le principe est normalement ok.


Message édité par pop-pan le 19-06-2012 à 12:12:57

---------------
[VDS] rail vesa, bras ecran, support TV / [ACH] des machins
Reply

Marsh Posté le 19-06-2012 à 11:46:06    

Merci pour vos précisions et remarques.

Reply

Marsh Posté le 19-06-2012 à 12:02:02    

je t'ai commenté un peu tout ca.
sinon n'oublie pas d'echaper correctemment tes valeurs
mysql_real_escape($key) ou mysql_real_escape($value)
pour limiter les injections SQL (je sais plus c'est lequel pour postgres...)
 
tu peux aussi utiliser PDO et des statements pour faire ca propre.


---------------
[VDS] rail vesa, bras ecran, support TV / [ACH] des machins
Reply

Marsh Posté le 19-06-2012 à 12:10:35    

ah et sinon 'extract()' c'est le mal.. :)
 
a la limite 'extract($_POST, EXTR_PREFIX_ALL, "extracted_" );' pour prefixer ces nouvelles variables.


---------------
[VDS] rail vesa, bras ecran, support TV / [ACH] des machins
Reply

Marsh Posté le 19-06-2012 à 13:06:50    

C'est clair, extract(), vaut mieux éviter :/...


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed