这是一个很好的问题。感谢您转向准备好的发言。看来经过这么多年的奋斗,这个想法终于开始占据主导地位。
免责声明:将会有指向我自己网站的链接,因为我已经帮助人们使用 PHP 20 多年了,并且痴迷于撰写有关最常见问题的文章。
是的,这是完全可能的。看看我的文章,如何为 mysqli 创建搜索过滤器 https://phpdelusions.net/mysqli_examples/search_filter对于功能齐全的示例。
For the WHERE
部分,您所需要做的就是创建两个单独的数组 - 一个包含带有占位符的查询条件,另一个包含这些占位符的实际值,即:
WHERE
clause
$conditions = [];
$parameters = [];
if (!empty($_POST["content"])) {
$conditions[] = 'content LIKE ?';
$parameters[] = '%'.$_POST['content ']."%";
}
等等,适用于所有搜索条件。
那么你可以implode
所有条件使用AND
以绳为胶,获得一流WHERE
clause:
if ($conditions)
{
$where .= " WHERE ".implode(" AND ", $conditions);
}
所有搜索条件的例程都是相同的,但对于IN()
条款。
IN()
clause
有点不同,因为您需要添加更多占位符和更多值:
if (!empty($_POST["opID"])) {
$in = str_repeat('?,', count($array) - 1) . '?';
$conditions[] = "opID IN ($in)";
$parameters = array_merge($parameters, $_POST["opID"]);
}
这段代码将添加尽可能多的?
占位符到IN()
子句中的多个元素$_POST["opID"]
并将所有这些值添加到$parameters
大批。可以在我网站同一部分的相邻文章中找到相关解释。
完成后WHERE
子句,您可以移至查询的其余部分
ORDER BY
clause
您不能参数化 order by 子句,因为字段名称和 SQL 关键字不能用占位符表示。为了解决这个问题,我请求你使用白名单功能 https://phpdelusions.net/pdo_examples/order_by我正是为了这个目的而写的。有了它,您可以使您的 ORDER BY 子句 100% 安全但非常灵活。您所需要的只是预定义一个数组,其中包含 order by 子句中允许的字段名称:
$sortColumns = ["title","content","priority"]; // add your own
然后使用这个方便的函数获取安全值:
$orderField = white_list($_POST["column"], $sortColumns, "Invalid column name");
$order = white_list($_POST["order"], ["ASC","DESC"], "Invalid ORDER BY direction");
这是一个智能功能,涵盖了三种不同的场景
- 如果未提供任何值(即 $_POST["column"] 为空),将使用白名单中的第一个值,因此它作为默认值
- 如果提供了正确的值,它将在查询中使用
- 如果提供的值不正确,则会抛出错误。
LIMIT
clause
LIMIT
值已完美参数化,因此您只需将它们添加到$parameters
array:
$limit = "LIMIT ?, ?";
$parameters[] = $offset;
$parameters[] = $recordsPerPage;
最后组装
最后,你的查询将是这样的
$sql = "SELECT id, title, content, priority, date, delivery
FROM tasks INNER JOIN ... $where ORDER BY `$orderField` $order $limit";
并且可以使用下面的代码来执行
$stmt = $mysqli->prepare($sql);
$stmt->bind_param(str_repeat("s", count($parameters)), ...$parameters);
$stmt->execute();
$data = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
where $data
是一个常规数组,包含查询返回的所有行。