【问题标题】:Simplifying mysql filter query简化mysql过滤器查询
【发布时间】:2011-10-10 00:17:46
【问题描述】:

我正在构建一个平台,供选角经理对演员进行分类并能够浏览他们。我的表“演员”设置了名字、姓氏、电子邮件、电话、地址等。

我有一个browse.php 页面,其中有一个过滤结果的表单。这是我的课程,当字段为空时,我需要帮助简化以及摆脱通配符结果。

我将表单数据传递到一个数组 $search 中,该类检查数组部分是否已填充并写入 SQL 查询。

public function getActors($search) {
    if(isset($search)) {
        if($search["first_name"] == NULL) { $first_name = "LIKE '%'"; } else { $first_name = "LIKE '".$search["first_name"]."'"; }
        if($search["last_name"] == NULL) { $last_name = "LIKE '%'"; } else { $last_name = "LIKE '".$search["last_name"]."'"; }
        if($search["gender"] == NULL) { $gender = "LIKE '%'"; } else { $gender = " = '".$search["gender"]."'"; }
        if($search["address_state"] == NULL) { $address_state = "LIKE '%'"; } else { $address_state = " = '".$search["address_state"]."'"; }
        if($search["ethnicity"] == NULL) { $ethnicity = "LIKE '%'"; } else { $ethnicity = " = '".$search["ethnicity"]."'"; }
        if($search["status"] == NULL) { $status = "LIKE '%'"; } else { $status = " = '".$search["status"]."'"; }

        $sql = "SELECT * FROM actor WHERE
            first_name ".$first_name." AND
            last_name ".$last_name." AND
            gender ".$gender." AND
            address_state ".$address_state." AND
            ethnicity ".$ethnicity." AND
            status ".$status."
        ";          
    } else {
        $sql = "SELECT * FROM actor";   
    }
    $s = mysql_query($sql) or die (mysql_error());
    $numrows = mysql_num_rows($s);

    for($x=0; $x < $numrows; $x++){
        $actorArray[$x] = mysql_fetch_row($s);
    }
    return $actorArray;
}   

对简化此有任何帮助或建议吗?

【问题讨论】:

    标签: php mysql wildcard sql-like


    【解决方案1】:

    对于条件,我可以使用 foreach 循环。

     if(isset($search)) {
            $conditions = array();
            foreach($search as $k => $criteria){
                if ($criteria != NULL){
                    $condition[] = "{$k} LIKE '{$criteria}'";
                    //this will produce for $search['first_name'] = 'john'
                    //  "first_name LIKE 'john'"
                }
            }
            //we transform the array of conditions into a string
            $conditions = implode (' AND ', $conditions);
            $sql = "SELECT * FROM actor WHERE " . $conditions;
    
     }else{
            $sql = "SELECT * FROM actor";   
     }
    

    【讨论】:

    • 记得清理你的用户输入!!
    【解决方案2】:

    怎么样(在isset 块内)...

    $fields = array('first_name','last_name','gender','address_state','ethnicity','status');
    $parts = array();
    foreach($fields as $field) {
      if(!empty($search[$field])) {
        $parts[] = $field . ' LIKE "' . $search[$field] . '"';
      }
    }
    $sql = "SELECT * FROM actor WHERE " . implode(' AND ', $parts);
    

    正如@Dvir 所提到的,最好在 SQL 语句中使用位置参数。

    【讨论】:

    • 这很好用。我做 WHERE field LIKE '&' 的原因是因为我想不出一种足够聪明的方法来编译 SQL 字符串以知道在哪里插入“AND”和“WHERE”。这给了我更多的选择,更少的代码和我现在知道的内爆函数会有所帮助。谢谢!
    • 记得清理您的数据输入
    【解决方案3】:

    LIKE '%'?严重地?如果它为空,为什么不直接不包含特定子句?

    此外,您的查询容易受到SQL injections 的攻击。

    阅读完 SQL 注入后,您可以通过遍历 $search 数组、添加特定子句并绑定参数来添加 WHERE 子句。

    【讨论】:

    • 正如我在上面发布的那样,我不得不运行 LIKE '%',因为我不知道如何以及在何处插入 'AND' 并保持正确的 SQL 语法。感谢 SQL 注入的提示,这也只是在 DEV 阶段,所以稍后我将通过并保护进入数据库的输入。
    猜你喜欢
    • 2013-05-01
    • 1970-01-01
    • 2014-03-19
    • 1970-01-01
    • 2013-01-03
    • 2016-04-10
    • 2011-08-02
    • 1970-01-01
    • 2012-11-17
    相关资源
    最近更新 更多