2009-08-07 7 views
3

Cela semble une tâche si simple, mais j'ai du mal à trouver une solution qui me plaise. Je ne trouve rien que je considérerais autre chose que maladroit. Voici ce que je travaille avec:Construire une requête MySQL basée sur des variables affichées

Il existe un formulaire de recherche qui enregistre des variables dans le script de traitement. Ces variables sont les filtres pour les données interrogées. Selon les droits de l'utilisateur, il peut y avoir plus ou moins de variables entrant, en fonction des filtres auxquels il a accès. Chaque filtre fait référence à un champ dans la table dont les résultats proviennent, fondamentalement. Une option pour chaque filtre est également "ANY", donc aucune clause WHERE n'est nécessaire.

Quelle est une bonne façon de construire la chaîne de requête. Disons qu'il y a quatre variables qui reviennent: $ firstname, $ lastname, $ age, $ dob. Mais seuls certains utilisateurs ont accès au filtre par $ age et $ dob.

$query = "SELECT * FROM people"; 
if(($firstname != 'ANY' && !empty($firstname)) || 
    ($lastname != 'ANY' && !empty($lastname)) || 
    ($age != 'ANY' && !empty($age)) || 
    ($dob != 'ANY' && !empty($dob))) { 
    $query .= " WHERE"; 
} 

if($firstname != 'ANY' && !empty($firstname)) { 
    $query .= " firstname='$firstname'"; 
} 
if($lastname != 'ANY' && !empty($lastname)) { 
    if($firstname != 'ANY' || !empty($firstname)) { 
     $query .= " AND"; 
    } 
    $query .= " lastname='$lastname'"; 
} 
... 

Et ainsi de suite. Mais ça a l'air idiot, horrible et ridiculement inefficace pour moi. J'utilise un pattern MVC légèrement modifié, alors est-ce qu'il serait logique de construire des méthodes dans le modèle de recherche pour chaque filtre possible?

+0

En note, ce qui est peut-être fait, mais écourtez l'espace, spécifiez vos champs au lieu d'utiliser *. –

Répondre

5

Je vais pour cela:

 
$query = "SELECT * FROM people"; 

$whereClause = " WHERE 1 = 1 "; 
if($firstname != 'ANY' && !empty($firstname)) { 
    $whereClause .= " AND firstname='$firstname' "; 
} 
if($lastname != 'ANY' && !empty($lastname)) { 
    $whereClause .= " AND lastname='$lastname' "; 
} 

$query .= $whereClause; 

Vous pourriez aussi recueillir toutes les déclarations dans un tableau et juste aller:

 
if (count($arr)>0) { 
    $query = "$query 
       WHERE ". implode(" AND ",$arr); 
} 
+0

Jamais pensé à une telle approche. J'ai toujours l'impression qu'il y a une sorte de motif ou quelque chose que je pourrais suivre, mais cela va au moins nettoyer le code pour l'instant. –

+0

C'est une approche plus propre. En fait, je suis en mesure d'améliorer mon code à partir de l'ouverture de Nathan et de cette réponse. Je crois que la réponse générale à la question de Nathan est "Ouais, PHP peut sembler un peu compliqué. Je vais rester à l'écoute - peut-être que je me trompe. (Et peut-être que je devrais regarder dans PDO, par autre réponse affichée.) – Smandoli

+0

En traitant de plusieurs variables et, en fonction de leur valeur, le résultat final change - il va être alambiqué n'importe quoi. La différence est de le rendre plus facile à lire plutôt que désordonné. Je joue toujours avec - j'ai vraiment l'impression qu'il y a quelque chose qui me manque encore. –

0
+0

Malheureusement, je n'utilise aucune sorte de PDO à ce stade; bien que ce soit vraiment quelque chose que je regarde. J'ai hérité une partie de ce code et je ne peux que changer en une seule fois. –

+0

L'utilisateur est redirigé vers: http://github.com/indeyets/MySQL-Query-Builder/tree/master – Smandoli

0

Voici un code qui va tirer toutes les variables postées et les enchaîner toge ther.

foreach($_POST as $name=>$value){ 
    $arrFields[] = $name." = '".$value."'"; 
} 
$sSql = "SELECT * FROM people WHERE 1 AND ".implode(" AND ",$arrFields); 

OU si vos noms de champs ne sont pas les mêmes que vos noms de table, ou si vous voulez traiter les champs différemment dans votre SQL, vous pouvez utiliser un commutateur.

foreach($_POST as $name=>$value){ 
    switch($name){ 
     case "firstname": 
      $arrFields[] = "fName = '".$value."'"; 
      break; 
     case "lastname": 
      $arrFields[] = "lName = '".$value."'"; 
      break; 
     case "age": 
      $arrFields[] = "bioAge >= ".$value; 
      break; 
    } 
} 
$sSql = "SELECT * FROM people WHERE 1 AND ".implode(" AND ",$arrFields); 
Questions connexes