动态创建WHERE子句PHP / MySQL

时间:2012-01-28 10:17:34

标签: php mysql

我正在动态生成MySQL查询的WHERE部分。我的代码到目前为止完美无缺

请注意: _GET字符串在我的代码中都经过验证,但是为了将这段代码保持在合理的长度,我将它们直接放在下面。对于任何想要做类似于我正在做的事情并且在这里使用我的代码作为基础的人,请务必验证你的字符串以避免mysql注入。

  /* Loop through each column in the table */

        for ( $i=0 ; $i<count($aColumns) ; $i++ )
        {
             /* check if the column has been marked as searchable and that the param sent from the client contains data */
            if ( $_GET['bSearchable_'.$i] == "true" && $_GET['sSearch_'.$i] != '' )
            {
                if ( $sWhere == "" )
                {
                    $sWhere = "WHERE ";
                }
                else
                {
                    $sWhere .= " AND ";
                }



/* RANGE FILTER CODE - This part is not important to this question but included for completenes */

                $columnFilterValue = mysql_real_escape_string($_GET['sSearch_' . $i]);
                // check for values range
                $rangeSeparator = "~";
                if (!empty($rangeSeparator) && strstr($columnFilterValue, $rangeSeparator)) {
                    // get min and max

                     $columnFilterRangeMatches =  explode('~', $columnFilterValue);

                    // get filter
                    if (empty($columnFilterRangeMatches[0]) && empty($columnFilterRangeMatches[1]))
                        $sWhere .= " 0 = 0 ";
                    else if (!empty($columnFilterRangeMatches[0]) && !empty($columnFilterRangeMatches[1]))
                        $sWhere .= $aColumns[$i] . " BETWEEN '" . $columnFilterRangeMatches[0] . "' and '" . $columnFilterRangeMatches[1] . "' ";
                    else if (empty($columnFilterRangeMatches[0]) && !empty($columnFilterRangeMatches[1]))
                        $sWhere .= $aColumns[$i] . " < '" . $columnFilterRangeMatches[1] . "' ";
                    else if (!empty($columnFilterRangeMatches[0]) && empty($columnFilterRangeMatches[1]))
                        $sWhere .= $aColumns[$i] . " > '" . $columnFilterRangeMatches[0] . "' ";
                } else {



    /* Begin building WHERE clause */


        $sWhere = "WHERE (";

                $aORs = array();

                    for ( $i=0 ; $i<count($aColumns) ; $i++ )
                            {
                                if ( $_GET['bSearchable_'.$i] == "true" && $_GET['sSearch_'.$i] != '' )
                                        {
                                                    $value = $_GET['sSearch_'.$i];

                                                        array_push($aORs, $aColumns[$i]." IN ($value)");


                                        }
                            }
                $sWhere .= implode(" OR ",$aORs);   

        $sWhere .= ')';
                }
            }
        }

现在这个代码执行的是它从客户端发送的逗号分隔值字符串,并根据这些值构建WHERE分支。

  • $ aColumns是一个包含表格中
  • 列的数组

实施例: -

如果参数......

  • sSearch_1包含值1,3,5,6
  • sSearch_2包含值1,2,3
  • sSearch_4包含值4,5,6
  • sSearch 6获得的值为7,8,9

然后,此代码将生成以下WHERE子句:

 WHERE genre_id IN (1,3,5,6) OR instruments IN (1,2,3) OR emotions IN (4,5,6) OR ratings IN (7,8,9)

这很好但是我想通过发送另一个包含正确顺序的OR和AND列表的字符串来使OR或AND动态化。

所以例如如果$ _GET ['filtertype'] =这样的字符串: -

OR,OR,AND

然后它应该返回:

WHERE genre_id IN (1,3,5,6) OR instruments IN (1,2,3) OR emotions IN (4,5,6) OR ratings IN (7,8,9)

正如您在上面的代码中所看到的,我正在通过implode函数将OR注入到我的数组中。 (代码的相关部分在下面重复)

  $sWhere = "WHERE (";

                $aORs = array();

                    for ( $i=0 ; $i<count($aColumns) ; $i++ )
                            {
                                if ( $_GET['bSearchable_'.$i] == "true" && $_GET['sSearch_'.$i] != '' )
                                        {
                                                    $value = $_GET['sSearch_'.$i];

                                                        array_push($aORs, $aColumns[$i]." IN ($value)");


                                        }
                            }
                $sWhere .= implode(" OR ",$aORs); 

        $sWhere .= ')';

如何根据正确的循环修改它以基本上添加正确的AND或OR?

1 个答案:

答案 0 :(得分:3)

我不是创建一个where字符串,而是先创建一个包含where部分的数组。

$whereParts = array();
foreach($aColumns as $i => $column)
{
    <logic goes here>
    $whereParts[] = 'genre_id IN (1,3,5,6)'; // sample :)
}

$where = 'WHERE ' . implode(' OR ', $whereParts); // note the spaces around OR

然后可以轻松地将' OR '替换为' AND '

允许用户在所有部件中选择AND和OR之间很容易,但如果你想为每个单独的项目选择,则不行。这也是一个逻辑问题。当用户指定a OR b AND c时,他会想要(a OR b) AND c还是a OR (b AND c)