2011-12-20 60 views
4

摘要

我目前使用"$search_field LIKE '$this->db->escape_like_str($search_string)%'";來轉義動態創建的搜索查詢。生成的SQL語句不會產生任何錯誤,但也不會產生任何結果。以下是我正在做的事情的詳細描述。如何正確地轉義mysql「search/like」查詢?

詳細

我使用的jqGrid和搜索功能。當用戶輸入搜索條件時,它將$filters json對象發佈到我的服務器。然後我解析它並創建一個SQL語句來獲取請求的數據。

這裏是逃避傳入搜索數據的代碼(這也是問題區域):

$search_string_like = $this->CI->db->escape_like_str($search_string); 
$operator['bw'] = "$search_field LIKE '$search_string_like%'"; //begins with 

下面是導致SQL語句:

SELECT * 
FROM player_data_temp_table 
WHERE first_name LIKE '\'zech\'%' AND last_name LIKE '\'camp\'%' 
ORDER BY date_won desc 
LIMIT 0 , 15 

此查詢不丟任何錯誤,但它也不起作用。當我在phpmyadmin中直接運行類似的查詢時,我得到了MySQL returned an empty result set (i.e. zero rows).,即使我知道有結果可以找到。如果我只是從first_name LIKE '\'zech\'%'中刪除反斜槓和單引號使其成爲first_name LIKE 'zech%',那麼我會得到預期的結果。我的擔心是,這不再適當逃脫,對吧?

用於構建查詢

摘要

一種可變,$filters,與如本{"groupOp":"AND","rules":[{"field":"first_name","op":"bw","data":"zech"}]}數據代碼被傳遞到build_where_clause($filters)build_where_clause返回完整的$where聲明,然後在模型中用於創建最終的SQL搜索語句。

jqgrid_lib.php

class jqgrid_lib 
{ 
private $CI; 

public function __construct() 
{ 
    $this->CI =& get_instance(); 
} 

/** 
* Function takes a json string with search rules and turns it into an sql statement. 
* 
* To use this function make sure you set stringResult: true, see example below: 
* $("#list").jqGrid('filterToolbar',{stringResult: true}); 
* @param json string  
* @author zechdc 
*/ 
public function build_where_clause($filters) 
{ 
    $sql_fragments = array(); 

    $filters = json_decode($filters); 
    $rules = $filters->rules; 
    $group_op = $filters->groupOp; 

    //loop through each rule and create an sql statement 
    foreach($rules as $rule) 
    { 
     $temp_sql = $this->create_search_field($rule->field, $rule->data, $rule->op); 
     array_push($sql_fragments, $temp_sql); 
    } 

    //combine all sql fragments with the group_operator 
    $data['sql'] = implode(' ' . $group_op . ' ', $sql_fragments); 

    return $data; 
} 

/** 
* Takes a field, string and search condition and turns it into a sql search statement 
* 
* To use this function make sure you set stringResult: true, see example below: 
* $("#list").jqGrid('filterToolbar',{stringResult: true}); 
* @param json string 
* @return string 
* @author zechdc 
*/ 
public function create_search_field($search_field, $search_string, $search_operator) 
{ 
    //$search_field = $this->CI->db->escape($search_field); //escaping the column breaks it. 
    $search_string = $this->CI->db->escape($search_string); 
    $search_string_like = $this->CI->db->escape_like_str($search_string); 
    //$search_string_like = $search_string; 

    $operator['eq'] = "$search_field=$search_string"; //equal to 
    $operator['ne'] = "$search_field<>$search_string"; //not equal to 
    $operator['lt'] = "$search_field < $search_string"; //less than 
    $operator['le'] = "$search_field <= $search_string "; //less than or equal to 
    $operator['gt'] = "$search_field > $search_string"; //less than 
    $operator['ge'] = "$search_field >= $search_string "; //less than or equal to 
    $operator['bw'] = "$search_field LIKE '$search_string_like%'"; //begins with 
    $operator['bn'] = "$search_field NOT LIKE '$search_string_like%'"; //not begins with 
    $operator['in'] = "$search_field IN ($search_string)"; //in 
    $operator['ni'] = "$search_field NOT IN ($search_string)"; //not in 
    $operator['ew'] = "$search_field LIKE '%$search_string_like'"; //ends with 
    $operator['en'] = "$search_field NOT LIKE '%$search_string_like%'"; //not ends with 
    $operator['cn'] = "$search_field LIKE '%$search_string_like%'"; //in 
    $operator['nc'] = "$search_field NOT LIKE '%$search_string_like%'"; //not in 
    $operator['nu'] = "$search_field IS NULL"; //is null 
    $operator['nn'] = "$search_field IS NOT NULL"; //is not null 

    if(isset($operator[$search_operator])) 
    { 
     //set the sql search statement 
     return $operator[$search_operator]; 
    } 
} 
} 

型號

/* 
* Gets all columns from table with limit and sort order set dynamically 
*/ 
function get_specific($sidx, $sord, $start, $limit, $where = NULL) 
{ 
    $result = FALSE; 

    if($where) 
    { 
     $where = ' WHERE ' . $where; 
    } 

    // usually I dont do select all but since this whole table is temp and only holds the needed data 
    // then just do select all. 
    $sql = "SELECT * 
      FROM player_data_temp_table 
      $where 
      ORDER BY $sidx $sord 
      LIMIT $start , $limit"; 

    $q = $this->db->query($sql); 

    if($this->db->affected_rows() > 0) 
    { 
     $result = $q->result(); 
    } 

    return $result; 
} 

UPDATE /答:

它看起來像我固定的問題。在這個模型中我去掉了手工製作$ sql語句,並與

if($where) 
    { 
     $this->db->where($where); 
    } 

    $this->db->order_by($sidx, $sord); 
    $q = $this->db->get('player_data_temp_table', $limit, $start); 

這似乎正確轉義所有的變量包括在$我的列名where語句替換它。

+1

這個子句有個問題:「我只是從'first_name LIKE'\'zech \'%''刪除斜槓,使它成爲'first_name LIKE'zech%''」。我想你的意思是「我只是刪除反斜槓**和單引號**」? – ruakh 2011-12-20 23:08:00

+0

只是爲了澄清,您在escape_like_str()函數調用之前或之後提供的查詢字符串? – 2011-12-20 23:09:45

+0

@ruakh是的你是對的,我會更新我的文章。 – zechdc 2011-12-20 23:10:22

回答

0

Manual

$這 - > DB-> escape_like_str()當字符串是在LIKE條件下使用,應使用這種方法,使得LIKE通配符( '%', '_')在該字符串也正確逃脫。

$search = '20% raise'; 
$sql = "SELECT id FROM table WHERE column LIKE '%".$this->db->escape_like_str($search)."%'"; 

所以,你這樣做是正確的代碼的最後兩行。


下面的代碼爲您做了什麼?

$search_string = 'zech'; 
$search_string_like = $this->CI->db->escape_like_str($search_string); 
$operator['bw'] = "$search_field LIKE '$search_string_like%'"; 
+0

我認爲這是正確的,但它不起作用。使用你發佈的代碼給了我一些像'first_name LIKE'\'zech \'%''。它運行時沒有錯誤,但不會返回任何結果。如果我將它改爲'first_name LIKE'zech%'',它會返回預期的結果。這就是我困惑的原因。我以爲我正在通過使用'$ this-> db-> escape_like_str($ search)'來完成它,但它不起作用。那麼我做錯了什麼? – zechdc 2011-12-20 23:15:21

+1

@zechdc $ search的內容是什麼? – CodeCaster 2011-12-20 23:22:34

+0

那麼在我上面評論的例子中,'$ search'的內容應該是'zech' – zechdc 2011-12-20 23:24:41