
devextreme等前端数据网格组件在进行远程数据过滤时,通常会发送一个结构化的json对象,其中包含一个filter字段。这个filter字段是一个数组,它以一种类似lisp或nosql的语法来表达过滤条件。例如:
{
"from": "get_data",
"skip": 0,
"take": 50,
"requireTotalCount": true,
"filter": [["SizeCd","=","UNIT"],"or",["SizeCd","=","JOGO"]]
}其中filter数组的结构特点是:
我们的目标是将这样的数组转换为形如WHERESizeCd= 'UNIT' ORSizeCd= 'JOGO'的MySQL WHERE子句。
使用PDO(PHP Data Objects)是PHP中推荐的数据库交互方式,因为它支持预处理语句,能够有效防止SQL注入。我们将创建两个辅助函数:一个用于生成带有占位符的SQL查询字符串,另一个用于提取参数值。
假设我们有以下过滤数组:
$filterArray = [
["SizeCd","=","UNIT"],
"or",
["SizeCd","=","JOGO"],
"or",
["SizeCd","=","PACOTE"]
];arrayToQuery函数负责遍历过滤数组,根据数组元素的类型(条件数组或逻辑操作符)来构建SQL WHERE子句。对于条件数组,它将字段名用反引号包围,操作符直接使用,值则用?作为占位符。
<?php
/**
* 将过滤数组转换为带有占位符的SQL WHERE子句。
*
* @param string $tableName 目标表名。
* @param array $filterArray DevExtreme风格的过滤数组。
* @return string 包含WHERE子句的SQL SELECT语句。
*/
function arrayToQuery(string $tableName, array $filterArray) : string
{
// 确保表名被反引号包围,防止SQL注入(针对表名)。
$select = "SELECT * FROM `" . str_replace("`", "``", $tableName) . "` WHERE ";
$conditions = [];
foreach ($filterArray as $item) {
if (is_array($item)) {
// 处理单个条件:[字段名, 操作符, 值]
// 字段名用反引号包围,防止SQL注入(针对字段名)。
$fieldName = "`" . str_replace("`", "``", $item[0]) . "`";
$operator = $item[1];
// 值使用PDO占位符 '?'
$conditions[] = "{$fieldName} {$operator} ?";
} else {
// 处理逻辑操作符:"or", "and"
// 确保操作符是合法的SQL关键字
$lowerItem = strtolower($item);
if (in_array($lowerItem, ['and', 'or'])) {
$conditions[] = " {$lowerItem} ";
} else {
// 忽略或抛出异常,处理非法操作符
// 示例中简化处理,实际应用中应更严谨
}
}
}
// 将所有条件和逻辑操作符拼接起来
$select .= implode("", $conditions);
return $select;
}
?>arrayToParams函数负责从过滤数组中提取所有条件的值,这些值将作为PDO预处理语句的绑定参数。
<?php
/**
* 从过滤数组中提取所有参数值。
*
* @param array $filterArray DevExtreme风格的过滤数组。
* @return array 包含所有参数值的数组。
*/
function arrayToParams(array $filterArray) : array
{
$return = [];
foreach ($filterArray as $item) {
if (is_array($item)) {
// 提取条件数组中的第三个元素(即值)
$return[] = $item[2];
}
}
return $return;
}
?>将上述函数结合PDO进行实际查询:
<?php
// 示例过滤数组
$filterArray = [
["SizeCd","=","UNIT"],
"or",
["SizeCd","=","JOGO"],
"or",
["SizeCd","=","PACOTE"]
];
// 数据库连接(请替换为您的实际连接信息)
try {
$dsn = "mysql:host=localhost;dbname=your_database_name;charset=utf8mb4";
$username = "your_username";
$password = "your_password";
$conn = new PDO($dsn, $username, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false, // 禁用模拟预处理,使用真实预处理
]);
} catch (PDOException $e) {
die("数据库连接失败: " . $e->getMessage());
}
$tableName = "your_table_name"; // 您的表名
$sql = arrayToQuery($tableName, $filterArray);
$params = arrayToParams($filterArray);
echo "生成的SQL查询字符串: " . $sql . "\n";
echo "提取的参数: " . print_r($params, true) . "\n";
try {
$stmt = $conn->prepare($sql);
$stmt->execute($params);
$results = $stmt->fetchAll();
echo "查询结果:\n";
print_r($results);
} catch (PDOException $e) {
echo "查询执行失败: " . $e->getMessage() . "\n";
}
?>输出示例:
生成的SQL查询字符串: SELECT * FROM `your_table_name` WHERE `SizeCd` = ? or `SizeCd` = ? or `SizeCd` = ?
提取的参数: Array
(
[0] => UNIT
[1] => JOGO
[2] => PACOTE
)
查询结果:
Array
(
// ... 您的查询结果 ...
)如果您的项目仍在使用MySQLi扩展,并且无法切换到PDO,那么在构建动态SQL时,手动对值进行转义是至关重要的,以防止SQL注入。
arrayToQueryMysqli函数与arrayToQuery类似,但它直接将值嵌入到SQL字符串中,并在嵌入前使用$mysqli-youjiankuohaophpcnreal_escape_string()进行转义。
<?php
/**
* 将过滤数组转换为完整的MySQLi查询字符串,并对值进行转义。
*
* @param mysqli $mysqli MySQLi连接对象。
* @param string $tableName 目标表名。
* @param array $filterArray DevExtreme风格的过滤数组。
* @return string 包含WHERE子句的完整SQL SELECT语句。
*/
function arrayToQueryMysqli($mysqli, string $tableName, array $filterArray) : string
{
// 确保表名被反引号包围,防止SQL注入(针对表名)。
$select = "SELECT * FROM `" . $mysqli->real_escape_string($tableName) . "` WHERE ";
$conditions = [];
foreach ($filterArray as $item) {
if (is_array($item)) {
// 处理单个条件:[字段名, 操作符, 值]
// 字段名用反引号包围,并进行转义以防万一。
$fieldName = "`" . $mysqli->real_escape_string($item[0]) . "`";
$operator = $item[1];
// 值使用 real_escape_string 进行转义,并用单引号包围。
$escapedValue = "'" . $mysqli->real_escape_string($item[2]) . "'";
$conditions[] = "{$fieldName} {$operator} {$escapedValue}";
} else {
// 处理逻辑操作符:"or", "and"
$lowerItem = strtolower($item);
if (in_array($lowerItem, ['and', 'or'])) {
$conditions[] = " {$lowerItem} ";
}
}
}
$select .= implode("", $conditions);
return $select;
}
?><?php
// 示例过滤数组
$filterArray = [
["SizeCd","=","UNIT"],
"or",
["SizeCd","=","JOGO"],
"or",
["SizeCd","=","PACOTE"]
];
// 数据库连接(请替换为您的实际连接信息)
$mysqli = new mysqli("localhost", "your_username", "your_password", "your_database_name");
// 检查连接
if ($mysqli->connect_errno) {
die("数据库连接失败: " . $mysqli->connect_error);
}
$tableName = "your_table_name"; // 您的表名
$query = arrayToQueryMysqli($mysqli, $tableName, $filterArray);
echo "生成的SQL查询字符串: " . $query . "\n";
try {
$result = $mysqli->query($query);
if ($result) {
echo "查询结果:\n";
while ($row = $result->fetch_assoc()) {
print_r($row);
}
$result->free();
} else {
echo "查询执行失败: " . $mysqli->error . "\n";
}
} catch (Exception $e) {
echo "查询执行异常: " . $e->getMessage() . "\n";
} finally {
$mysqli->close();
}
?>输出示例:
生成的SQL查询字符串: SELECT * FROM `your_table_name` WHERE `SizeCd` = 'UNIT' or `SizeCd` = 'JOGO' or `SizeCd` = 'PACOTE'
查询结果:
Array
(
// ... 您的查询结果 ...
)通过本教程,我们学习了如何将DevExtreme等前端框架生成的类NoSQL过滤数组转换为可执行的MySQL WHERE条件语句。我们分别探讨了使用PDO预处理语句和MySQLi配合real_escape_string的两种方法,并强调了SQL注入防护的重要性。选择适合您项目需求的方法,并始终将安全性放在首位,以构建健壮、可靠的数据查询功能。
以上就是将DevExtreme过滤数组转换为MySQL WHERE条件语句的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号