简体   繁体   English

如何正确地逃避mysql“搜索/喜欢”查询?

[英]How do I escape a mysql “search / like” query properly?

Summary 摘要

I am currently using "$search_field LIKE '$this->db->escape_like_str($search_string)%'"; 我目前正在使用"$search_field LIKE '$this->db->escape_like_str($search_string)%'"; to escape dynamically created search queries. 逃避动态创建的搜索查询。 The resulting SQL statements created do not produce any errors but also do not produce any results. 生成的结果SQL语句不会产生任何错误,但也不会产生任何结果。 Below is a detailed description of what I am doing. 以下是我正在做的事情的详细说明。

Details 细节

I am using jqGrid and its search feature. 我正在使用jqGrid及其搜索功能。 When the user enters search terms it posts the $filters json object to my server. 当用户输入搜索词时,它会将$filters json对象发布到我的服务器。 I then parse it and create an SQL statement to get the data requested. 然后我解析它并创建一个SQL语句来获取请求的数据。

Here is the code for escaping the incoming search data (this is also the problem area): 这是用于转义传入搜索数据的代码(这也是问题区域):

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

Here is the resulting SQL statement: 以下是生成的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

This query doesn't throw any errors but it also doesn't work. 此查询不会抛出任何错误,但它也不起作用。 When I run a similar query directly in phpmyadmin I get, MySQL returned an empty result set (ie zero rows). 当我在phpmyadmin中直接运行类似的查询时, MySQL returned an empty result set (ie zero rows).得到MySQL returned an empty result set (ie zero rows). even though I know there are results to be found. 即使我知道有结果可以找到。 If I simply remove the backslashes and single-quotes from first_name LIKE '\\'zech\\'%' to make it first_name LIKE 'zech%' I then get the expected results. 如果我只是从first_name LIKE '\\'zech\\'%'删除反斜杠和单引号,使其成为first_name LIKE 'zech%' ,然后我得到预期的结果。 My concern is that this is no longer properly escaped, right? 我担心的是,这已经不再妥协了,对吗?

Code Used to Build the Query 用于构建查询的代码

Summary 摘要

A variable, $filters , with data such as this {"groupOp":"AND","rules":[{"field":"first_name","op":"bw","data":"zech"}]} is passed into build_where_clause($filters) . 变量$filters ,包含此{"groupOp":"AND","rules":[{"field":"first_name","op":"bw","data":"zech"}]}传递到build_where_clause($filters) build_where_clause returns the full $where statement and is then used in the Model to create the final SQL search statement. build_where_clause返回完整的$where语句,然后在Model中用于创建最终的SQL搜索语句。

jqgrid_lib.php 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];
    } 
}
}

Model 模型

/*
 * 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 / Answer: 更新/答案:

It looks like I fixed the issue. 看起来我修复了这个问题。 In the model I removed the hand made $sql statement and replaced it with 在模型中,我删除了手工制作的$ sql语句并将其替换为

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

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

That seemed to properly escape all the variables including my column names in the $where statement. 这似乎正确地逃避了所有变量,包括$ where语句中的列名。

Manual : 手册

$this->db->escape_like_str() This method should be used when strings are to be used in LIKE conditions so that LIKE wildcards ('%', '_') in the string are also properly escaped. $ this-> db-> escape_like_str()当在LIKE条件中使用字符串时,应使用此方法,以便字符串中的LIKE通配符('%','_')也被正确转义。

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

So you're doing it right in your last two lines of code. 所以你在最后两行代码中做得很好。


What does the following code do for you? 以下代码为您做什么?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM