2011-02-07 88 views
5

什麼是使用PHP下面的輸入轉換爲SQL的最佳方式?轉換自定義查詢到SQL

+a - includes a 
+(c\d) - includes c or d but not both 
+(c/d/e) - includes any of these 
-f - does not include f 

我已經使用preg_replace或爆炸來循環和做如果聲明,但沒有任何工作一貫工作的各種刺。

基本上,我需要把像

+a +(c/d/e) 

進入

SELECT * FROM the_table 
WHERE description LIKE "%a%" 
AND (description LIKE "%c%" OR description like "%d%" OR description LIKE "%$e%") 

謝謝!

UPDATE:

這是我在它的嘗試。我確信有一個更簡單的方法...

public function custom_query($query){ 

    $fields = " feed_items.description "; 

    $return_query = ""; 

    $query = str_replace("'", '', $query); 

    $pluses = explode('+',$query); 

    foreach($pluses as $plus){ 

      $plus = trim($plus); 

      if (substr($plus,0,1) == '('){ 
       $return_query .= 'AND ('; 

       $plus = str_replace(array('(',')'), '', $plus); 

       $ors = explode('/', $plus); 

       foreach($ors as $or){ 
        if ($or){ 
         $return_query .= $fields." LIKE '%".$or."%' OR"; 
        } 
       } 

       $return_query = rtrim($return_query, ' OR'); 
       $return_query .= ')'; 
      } else { 
       if ($plus){ 
        $return_query .= ' AND ' . $fields.' LIKE '.'"%'.$plus.'%"'; 
       } 
      } 

     } 

    $negatives = explode('-',$query); 

    foreach($negatives as $negative){ 

      $negative = trim($negative); 

      if (substr($negative,0,1) == '('){ 
       $return_query .= 'AND ('; 

       $negative = str_replace(array('(',')'), '', $negative); 

       $ors = explode('\\', $negative); 

       foreach($ors as $or){ 
        if ($or){ 
         $return_query .= $fields." NOT LIKE '%".$or."%' OR"; 
        } 
       } 

       $return_query = rtrim($return_query, ' OR'); 
       $return_query .= ')'; 
      } else { 
       if ($negative){ 
        $return_query .= ' AND ' . $fields.' NOT LIKE '.'"%'.$negative.'%"'; 
       } 
      } 

     } 

    $return_query = ' AND '.ltrim($return_query, ' AND '); 

    return $return_query; 

} 

回答

1

由於您不需要嵌套表達式。它的簡單和正則表達式實際上只是懶惰:

$sql = preg_replace_callback("' 
      ([+-])   # AND or NOT 
      (\w+    # capture a single word 
      | \(    # or something enclosed in literal braces 
       (\w+   # word 
        ([/\\\\])? # logical delimiter 
       [^)]*)  # remainder words and/or delimiters 
      \) 
      )'x", 
     "to_sql", $search_pattern); 

function to_sql($match) { 
    @list($uu, $logical, $word, $words, $or) = $match; 

    if ($logical == "+") { 
     $sql = " AND ("; 
    } 
    else { 
     $sql = " OR ("; 
    } 

    if ($words) { 
     $words = explode($or, $words); 
    } 
    else { 
     $words = array($word); 
     $or = "/"; 
    } 

    foreach ($words as $i=>$word) { 
     $words[$i] = "description LIKE '%$word%'"; 
    } 

    $or = ($or == "/") ? " OR " : " XOR "; 
    $sql .= implode($or, $words); 

    return "$sql)"; 
} 

這將返回的聲明開頭「AND」,它可以適應,但它更容易欺騙,只是在前面加上「TRUE」把它變成一個有效的WHERE子句。

1
$pattern = "+a +(c/d/e)"; 

// replace a, c, d, e with "description like "%something%" 
$pattern = preg_replace('#[^()+\\-\\\\/\s]#', 'description like "%$0%"', $pattern); 

// replace operators 
$replacements = array(
    '+' => ' and ', 
    '-' => ' and not ', 
    '\\' => ' xor ', 
    '/' => ' or ', 
); 
$pattern = str_replace(array_keys($replacements), $replacements, $pattern); 
$pattern = trim($pattern); 

// remove first "and" 
// * "and something and something_else" becomes "something and something_else" 
// * "and not something and something_else" becomes "not something and something else" 
$pattern = preg_replace('#^and #', '', $pattern); 

彭定康應+-或沒有任何運營商開始。

不知道有關與xor更換\ - 取決於你想如何處理(a\b\c)(a\b\c\d)