我正在动态生成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
- 搜索6个cnt的值为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)
正如您在上面的代码中所看到的,我目前正在通过内爆函数将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?
我不创建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
那么用' AND '
代替' OR '
就很容易了
允许用户为所有where部件在AND和OR之间进行选择是很容易的,但如果您想为每个单独的项目进行选择,则不需要这样做。这也是一个逻辑问题。当用户指定a OR b AND c
时,他想要(a OR b) AND c
还是a OR (b AND c)
?