2009-08-07 59 views
3

這似乎是一個如此簡單的任務,但我很難找到我喜歡的解決方案。除了笨重之外,我找不到任何其他的東西。以下是我正在處理的內容:基於發佈的變量構建MySQL查詢

有一個將變量發佈到處理腳本的搜索表單。這些變量是被查詢數據的過濾器。取決於用戶的權限,可能會有更多或更少的變量進入,具體取決於他們可以訪問的過濾器。基本上,每個過濾器都是指表格中結果來自的一個字段。每個過濾器的一個選項也是「ANY」,所以不需要WHERE子句。

什麼是構建查詢字符串的好方法。假設有四個變量返回:$ firstname,$ lastname,$ age,$ dob。但只有一些用戶可以通過$ age和$ 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'"; 
} 
... 

依此類推。但對我來說,這看起來很愚蠢,可怕,而且效率低得可笑。我正在使用稍微修改過的MVC模式,那麼爲每個可能的過濾器構建搜索模型中的方法是否合理?

+0

作爲一個側面說明,您可以完成,但縮小了空間,請指定您的字段,而不是使用*。 – 2009-08-07 14:55:31

回答

5

我會去這樣的:

 
$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; 

你可以或者收集所有語句到一個數組,只是去:

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

從來沒有想過這樣的方法。我仍然覺得有某種模式或我可以遵循的某種模式,但至少現在會清理代碼。 – 2009-08-07 14:44:19

+0

這是一個更乾淨的方法。事實上,我可以從Nathan的揭幕戰和這個回覆中改進我的一些代碼。我相信Nathan的問題的一般答案是「是的,PHP可能看起來有點複雜,對不起'這個!」我會繼續關注 - 也許我錯了。 (也許我應該看看PDO,根據其他發佈的答案。) – Smandoli 2009-08-07 14:49:59

+0

當處理多個變量時,根據它們的值,最終結果會發生變化 - 無論如何,它都會變得複雜。不同之處在於使閱讀更容易,而不是更麻煩。我仍然在玩它 - 我真的覺得我還有一些東西還沒有找到。 – 2009-08-07 15:18:58

0
+0

不幸的是,我現在沒有使用任何類型的PDO;儘管這是我正在研究的東西。我繼承了一些這樣的代碼,我只能一次性改變這麼多。 – 2009-08-07 14:43:15

+0

用戶被重定向到:http://github.com/indeyets/MySQL-Query-Builder/tree/master – Smandoli 2009-08-07 14:45:04

0

這裏有一些代碼將拉動所有發佈的變量並將它們串起來療法。

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

如果你的字段名是不一樣的你的表名,或者,如果你想在你的SQL區別對待的領域,你可以使用一個開關。

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);