Recherche multi-critères

Recherche multi-critères - PHP - Programmation

Marsh Posté le 29-05-2010 à 17:20:30    

Bonsoir,
 
Je suis en train de configurer un système de recherche qui se veut relativement complet, et je bloque sur la bonne requête à effectuer.
 
Premier problème : mettons qu'on puisse rechercher dans une liste de livres. On veut pouvoir chercher un auteur en particulier, un titre, un thème, etc. Comment peut-on configurer la requête pour faire en sorte qu'elle ne plante pas lorsqu'un champ n'est pas rempli ? Pour parer ça, j'ai mis des conditions en LIKE "%'.$auteur.'%" qui fait marcher la requête même si la variable est nulle, mais je ne suis pas sûr que ce soit la solution optimale.
 
Deuxième problème, plus emmerdant. Imaginons que certains bouquins soient écrits par plusieurs personnes. Les caractéristiques de chaque livre sont archivés dans une table, et une autre table archive les auteurs et les infos les concernant, avec un champ id_livre pour faire la jonction entre les deux. Mais je ne sais pas comment afficher tous les livres écrits conjointement par Claude et Jacky.
 
Pour l'instant, j'ai un truc du genre :

Code :
  1. SELECT DISTINCT *tous mes machins*
  2. FROM livres l
  3. LEFT JOIN auteurs a
  4. ON l.id = a.bouquin_id
  5. WHERE l.titre LIKE "%'.$search_titre.'%"
  6. AND *pas mal d'autres options*
  7. AND a.nom LIKE "%'.$search_nom_1.'%"
  8. AND a.nom LIKE "%'.$search_nom_2.'%"

 
La chose marche parfaitement lorsqu'on ne cherche qu'un auteur en particulier, mais pour filtrer les résultats à deux auteurs, ça foire lamentablement.
 
Merci d'avance :)


---------------
Plaît-il ?
Reply

Marsh Posté le 29-05-2010 à 17:20:30   

Reply

Marsh Posté le 29-05-2010 à 17:44:07    

pour le premier problème :

Code :
  1. $query = "SELECT DISTINCT *tous mes machins*
  2. FROM livres l
  3. LEFT JOIN auteurs a
  4. ON l.id = a.bouquin_id
  5. WHERE 1 = 1 ";
  6. if($titre)
  7. {
  8.      $titre = mysql_real_escape_string($titre);
  9.      $query.=" AND titre LIKE $titre";
  10. }
 

pour le second, c'est encore plus fun
pour chaque critère auteur tu vas faire une jointure, tu vas avoir un truc du genre :

 
Code :
  1. $joinAuteur  ='';
  2. $whereAuteur = '';
  3. $compteurAuteur = 0;
  4.  
  5. foreach($auteurs as $auteur)
  6. {
  7.      $alias = 'a'.$compteurAuteur;
  8.      $joinAuteur  .= ' LEFT JOIN auteur as '.$alias // pour avoir un alias de table unique
  9.      $joinAuteur  .= 'ON l.id = '.$alias .'.bouquin_id';
  10.      $auteur = mysql_real_escape_string($auteur);
  11.      $whereAuteur  .= "AND $alias.nom LIKE '%$auteur%'";
  12.  
  13. }
  14. $query =" SELECT DISTINCT *tous mes machins*
  15. FROM livres l
  16. $joinAuteur
  17. WHERE l.titre LIKE \"%'.$search_titre.'%\"
  18. $whereAuteur "

Message cité 1 fois
Message édité par flo850 le 29-05-2010 à 17:45:04
Reply

Marsh Posté le 29-05-2010 à 18:38:06    

Wow, j'étais à des années-lumières de me douter qu'on pouvait faire plusieurs LEFT JOIN dans une même requête. Merci pour l'astuce.
 
Par contre, je ne comprends pas bien les variables $auteurs et $auteur. Surtout la $auteurs, en fait.
J'ai essayé de mettre mes deux variables d'auteur différentes dans un array du type  

Code :
  1. $auteurs = array($search_auteur_1,$search_auteur_2);


mais la requête ne retourne alors aucun résultat.
 
Autre point obscur, c'est cette histoire de $compteurAuteur. S'il reste fixe, on n'obtient a priori pas un alias unique, si ? Ou je suis censé le faire varier selon le nombre d'auteurs passés en variable ?
 
 
 
Edit : Suite à ta solution très élégante qui donne une requête très flexible, j'ai très barbarement fait rentrer les deux LEFT JOIN de force. Ca me donne à peu près ça :
 

Code :
  1. $query = 'SELECT DISTINCT *tous mes machins*
  2. FROM livres l
  3. LEFT JOIN auteurs a1
  4. ON l.id = a1.bouquin_id
  5. LEFT JOIN auteurs a2
  6. ON l.id = a2.bouquin_id
  7. WHERE l.titre LIKE "%'.$search_titre.'%"
  8. AND *pas mal d'autres options*
  9. AND a1.nom LIKE "%'.$search_nom_1.'%"
  10. AND a2.nom LIKE "%'.$search_nom_2.'%" ';


 
A ne pas reproduire chez soi, ça tache.
 
Merci encore pour ton aide  :jap:
 
 
Re-Edit : En fait, j'ai un nouveau problème. Imaginons qu'on ait aussi rentré la nationalité de chaque auteur dans la table auteurs. J'aimerais qu'en rentrant $search_nationalite_1 = "français" et $search_nationalite_2 = "français", on n'obtienne que les livres écrits par deux français. D'où le code suivant :
 

Code :
  1. SELECT DISTINCT *tous mes machins*
  2. FROM livres l
  3. LEFT JOIN auteurs a1
  4. ON l.id = a1.bouquin_id
  5. LEFT JOIN auteurs a2
  6. ON l.id = a2.bouquin_id
  7. WHERE l.titre LIKE "%'.$search_titre.'%"
  8. AND *pas mal d'autres options*
  9. AND a1.nationalite LIKE "%'.$search_nationalite_1.'%"
  10. AND a2.nationalite LIKE "%'.$search_nationalite_2.'%"


 
Le problème, c'est qu'avec ça, j'obtiens aussi les livres écrits par un seul français. Il faudrait donc que je sépare les résultats trouvés par la requête en a1 et a2 (histoire d'éviter qu'ils n e piochent dans la même ligne), mais je ne vois vraiment pas comment.


Message édité par Brendeldas le 29-05-2010 à 19:35:46

---------------
Plaît-il ?
Reply

Marsh Posté le 29-05-2010 à 19:52:09    

pour le tableuax auteurs, c'ets juste un tableau d'auteurs, tu as bien compris ( j'i eu la flemme de recopier tes noms de variables :d)  
 
tu as bien bien vu il faut faire $compteurAuteur ++ a la fin de la boucle
 
 
j'ai oublié un "détail", il faut que a1 et a2 retournent des résultats différents  
donc il faut ajouter a1.Id <> a2.id dans le second join  
avec 3 , ça devient pire  il faut ajouter a1.id <> a2.id aND a2.id <> a3.id and a1.id <> a3.id  
 
sinon, tu as des trucs qui existent, comme sphinx pour se simplifier la vie.  
 
Tu as aussi la possibilité de construire une table agglomérée, constitués de champs TEXT ou LONGTEXT,  contenant toutes les données à rechercher ( genre une colonne auteurs qui contient le nom de tous les auteurs )  
 
tu peux aussi faire une recherche sur la table auteur , puis lancer une requete sur la table livre avec les auteurs trouvés

Reply

Marsh Posté le 29-05-2010 à 20:05:44    

Je viens de penser à l'astuce du a1.id != a2.id  :D  
 
Désolé de t'avoir dérangé pour ça, du coup.
 
Quoiqu'il en soit, merci infiniment pour ton aide :jap:


---------------
Plaît-il ?
Reply

Marsh Posté le 29-05-2010 à 20:13:12    

( si ça me dérange, je ne répond pas :d )  
 
bon courage ( au passage,  encore plus complexe, mais plus agréable pour l'utilisateur  : un seul champ de recherche qui va regarder dans toutes les tables)

Reply

Marsh Posté le 29-05-2010 à 21:34:52    

flo850 a écrit :

pour le premier problème :  

Code :
  1. $query = "SELECT DISTINCT *tous mes machins*
  2. FROM livres l
  3. LEFT JOIN auteurs a
  4. ON l.id = a.bouquin_id
  5. WHERE 1 = 1 ";
  6. if($titre)
  7. {
  8.      $titre = mysql_real_escape_string($titre);
  9.      $query.=" AND titre LIKE $titre";
  10. }




avec des guillemets autour de $titre dans la requête ce serait tout de suite plus sympa :o


---------------
Contes de fées en yaourt --- --- zed, souviens-toi de ma dernière lettre. --- Rate ta musique
Reply

Marsh Posté le 29-05-2010 à 21:40:17    

c'est un grand garçon, il a corrigé tout seul. ;)
(j'avais d'autres erreurs largement plus sales)

Reply

Marsh Posté le 29-05-2010 à 21:42:12    

J'sais pas, j'ai rien lu, c'est juste mon obsession du moment à cause de blablaweb :(


---------------
Contes de fées en yaourt --- --- zed, souviens-toi de ma dernière lettre. --- Rate ta musique
Reply

Marsh Posté le 29-05-2010 à 22:10:55    

certains débutent avec de bonnes bases puis montent des choses plus compliqués  
sur blablaweb , c'est l'inverse, c'est pour ça que je n'y participe quasi plus

Reply

Marsh Posté le 29-05-2010 à 22:10:55   

Reply

Marsh Posté le 29-05-2010 à 22:19:30    

ça dépend lesquels, lui il monopolise c'est pour ça :o


---------------
Contes de fées en yaourt --- --- zed, souviens-toi de ma dernière lettre. --- Rate ta musique
Reply

Sujets relatifs:

Leave a Replay

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