2011-02-07 14 views
5

Jaki byłby najlepszy sposób konwersji poniższych danych wejściowych na SQL przy użyciu PHP?Konwertowanie zapytań niestandardowych na 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 

miałem różne pchnięć użyciu preg_replace lub eksplodować pętli i zrobić if ale nie mam nic do pracy konsekwentnie.

I w zasadzie trzeba włączyć coś

+a +(c/d/e) 

Do

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

Dzięki!

UPDATE:

Oto moja próba na niego. Jestem pewien, że jest łatwiejszy sposób ...

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; 

} 

Odpowiedz

1

Ponieważ nie trzeba zagnieżdżać wyrażenia. To proste i regex jest rzeczywiście tylko lenistwo:

$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)"; 
} 

to wróci oświadczenie zaczynające się od „I”, które mogą być dostosowane, ale łatwiej jest oszukać i po prostu poprzedzić „true”, aby przekształcić go w prawidłowym Klauzula 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); 

Patten powinno rozpocząć +, - lub bez operatora.

Nie wiesz o wymianie \ z xor - zależy od tego, jak chcesz obsługiwać (a\b\c), (a\b\c\d) itp