最短的答案:是的。你可以控制一切。实现这一点所需要做的就是在表单中添加另一个选择元素,让用户控制比较值的方式。我将使用一个简化的示例。
如果您有用户值的输入:
<input type="number" name="age" value="" />
在它之前添加一个选择字段:
<select name="age_comparison">
<option value="equal">equal to</option>
<option value="not_equal">not equal to</option>
<option value="less_than">less than</option>
<option value="greater_than">greater than</option>
</select>
<input type="number" name="age" value="" />
注意:该位置与处理无关 - 根本没有。我只是认为,如果用户像阅读现实生活中的一段文字一样阅读您的页面,那将是一种更好的用户体验。这意味着当输入稍后出现时,它将读取为“年龄大于 X”,如果您将输入放在首位,则它比“年龄 X,大于”更好。
出于同样的原因(更好的用户体验),我倾向于用读起来更像人类的东西来标记选项,因此“等于”而不是“等于”。但是我从选项值中省略了它,因为它没有向代码添加任何有价值的信息(“等于”作为参数值讲述了整个故事)。
然后,在提交表单后,您可以检测用户的选择并相应地构建查询字符串:
if (isset($_GET['age'])) {
$age = $_GET['age'];
}
if (isset($_GET['age_comparison'])) {
switch ($_GET['age_comparison']) {
case 'equal':
$ageComparison = '=';
break;
case 'not_equal':
$ageComparison = '!=';
break;
case 'less_than':
$ageComparison = '<';
break;
case 'greater_than':
$ageComparison = '>';
break;
}
}
// if we have all the parameters, we can query the database
if (isset($age) && isset($ageComparison)) {
// the following line is very unsafe - we'll be on that in a minute
$queryString = 'SELECT * FROM students WHERE age '.$ageComparison.$age;
...
注意:我使用了$_GET,因为您在问题中使用了它。如果您要在表单中包含多个参数,我建议您宁愿使用post 方法,并避免将一大堆参数添加到页面的 url。您的表单值将位于相同的键下,仅在 $_POST 变量中。另外,当您使用post 时,检测是否设置了提交的名称就足够了——如果是,则保证来自同一表单的其余输入也存在。使用get,您必须单独检查每个参数。
所以你有它。带有变量比较运算符的查询。
但是
我们还没有完成。有一些不好的做法需要改掉,也有一些好的做法需要学习。
首先,永远不要通过直接插入参数来构建查询:
$sql = "SELECT * FROM `idk` where `alias` = '".$s."'";
这让您对SQL injection 敞开心扉。您应该改用prepared statements。准备好的语句具有内置的保护机制,还可以满足您的所有引用需求(这意味着您不必手动在字符串参数周围放置 uote 标记)。所以你这样做:
// the question mark means we'll be adding a parameter in that position
$queryString = 'SELECT * FROM students WHERE age '.$ageComparison.' ?';
// here I assume you have mysqli statement ready
// you can see an example about creating one in the link about prepared statements
$statement->prepare($queryString);
$statement->bindParam('i', $age);
你可能会说“但是等一下!你只是添加了比较运算符直接!这不是很危险吗?” - 不,因为它不是直接来自用户。我们在 switch 语句中决定了它的值,这意味着我们接受用户的输入(可能会受到损害)并将其转换为 我们控制的值。用户无法决定 switch 语句的结果,我们可以。因此,直接将其连接到查询字符串中是安全的,因为我们知道我们已经定义了一些安全值。
说到 switch 语句,这里也需要改进。如果我们在select 中添加另一个选项,但我们忘记在 switch 语句中添加它怎么办?还是恶意用户损害了正在发送的选项的价值?我们最终会得到一个错误,因为那时不会匹配 switch 中的任何情况(我们放在那里的 4 之外的值的情况没有定义),因此变量$ageComparison 将永远不会被创建,我们将永远不要执行查询,因为我们的 if 条件会失败。那么我们该如何解决呢?我们添加一个默认案例(当没有案例匹配时默认执行):
// remainder of statement cut for length
...
case 'greater_than':
$queryComparison = '>';
break;
default:
throw new Exception('Unsupported value for age comparison: '.$ageComparison);
}
异常在未处理时会停止执行(正确的术语是caught),但如果您想自己探索该主题,我会留给您(对于初学者来说似乎有点多) ,而且这里已经有相当多的文字了)。