首页 > 解决方案 > MySQL 表上可选的多个过滤器

问题描述

所以我有一个包含以下列的数据库表:

ID
Foo
Bar
Gux

Foo 可以保存值 [a, b, c]、Bar [1, 2, 3] 和 Gux [x, y, z]。

在我的界面中,我有一个 HTML 选择框来过滤 Foo、Bar 和 Gux。问题是用户可以按随机顺序过滤一个、两个或三个参数。

这给了我一个问题来进行有效的 SQL 查询和 bind_param。

我可以做这样的事情:

//Pseudo code

$sql = "";

if (isset($_GET['foo'])) {
    $sql = "SELECT * FROM ... WHERE foo=?";
}
if (isset($_GET['bar'])) {
    $sql = "SELECT * FROM ... WHERE bar=?";
}
if (isset($_GET['gux'])) {
    $sql = "SELECT * FROM ... WHERE gux=?";
}

但是如果使用选择了 foo 和 bar 呢?这也将非常难看且难以实现 bind_params。

理想将是一个通配符,所以我可以做

//Pseudo code

$sql = "SELECT * FROM ... WHERE foo=* AND bar=* AND gux=*";

并且仅在*选择该列的过滤器时将其替换为实际值。但这不支持整数。

我想到的另一个选择是执行以下操作:

//Pseudo code

$sql = "SELECT * FROM ... WHERE foo=filter1 OR bar=filter2 OR gux=filter3";

并在选择该列的值时以编程方式替换ORAND这也将解决 bind_param 问题。但我不知道这是否是最好的方法。

标签: phpmysql

解决方案


正如 RiggsFolly 所提到的,动态构建 WHERE 子句。此代码假定至少有 1 个选项(否则也有条件地添加 WHERE。)

每个部分都与相应的绑定数组一起添加到列表中,这显示了数据,您需要为数据库添加实际的 API 部分。WHERE 部分使用implode()withAND作为胶水放在一起...

$binds = [];
$where = [];
$types = '';
if (isset($_GET['foo'])) {
    $where[] = "foo=?";
    $binds[] = $_GET['foo'];
    $types .= "s";
}
if (isset($_GET['bar'])) {
    $where[] = "bar=?";
    $binds[] = $_GET['bar'];
    $types .= "s";
}
if (isset($_GET['gux'])) {
    $where[] = "gux=?";
    $binds[] = $_GET['gux'];
    $types .= "i";
}

$sql = "SELECT * FROM ... WHERE " . implode(" AND ", $where);

echo $sql.PHP_EOL;
print_r($binds);

foo 值中的 1 给出...

SELECT * FROM ... WHERE foo=?
Array
(
    [0] => 1
)

然后使用类型和绑定bind_param()...

bind_param($types, ...$binds);

推荐阅读