通过 $ Poles OR $ Power(或两者的组合)我选择行列表
if($_GET["Power"]!="*" and $_GET["Poles"]!="*") $query = "SELECT * FROM `TABLE 2` WHERE Power=".$_GET["Power"]." AND Poles=".$_GET["Poles"]."";
elseif($_GET["Poles"]!="*") $query.= "SELECT * FROM `TABLE 2` WHERE Poles=".$_GET["Poles"]."";
elseif($_GET["Power"]!="*") $query.= "SELECT * FROM `TABLE 2` WHERE Power=".$_GET["Power"]."";
else $query= "SELECT * FROM `TABLE 2` ORDER BY Power";
我绝对是初学者,但我觉得这是一种错误的做法。
请告诉我,应该怎么做?
答案 0 :(得分:3)
只要提供的信息,我认为您的逻辑通常可以实现您的目标。你有几个场景对我来说是截然不同的查询,所以我会处理用PHP构建查询的逻辑。
我不确定你是否使用任何类型的框架,但我会假设你不是,但我建议你这样做是否可行。一个好的框架将提供输入清理和数据库管理,使生活更轻松,并提供更多安全选项。
出于安全考虑,由于您使用直接来自用户的输入构建查询,我建议您使用PDO类与数据库进行交互(如果不是)。 PDO类将允许您将用户的输入绑定到查询,然后它将自动转义输入。这大大降低了SQL注入攻击的风险(用户使用他们向您提交的内容向您的数据库执行恶意操作),现在被认为是PHP的标准做法。
有关PDO课程的更多信息,请访问:http://php.net/manual/en/book.pdo.php
有关SQL注入攻击的更多信息,请访问:http://www.w3schools.com/sql/sql_injection.asp
所以这将是我未经测试的代码将它们放在一起:
$dsn = "localhost"; //Where is your DB located?
$username = "username";
$password = "password";
//Create new DB connection (http://php.net/manual/en/pdo.construct.php)
$dbh = new PDO($dsn, $username, $password);
//Craft and execute the appropriate query
//Each query will include placeholders for data (like :power)
//Placeholders will be replaced with the data passed to execute()
//The PDO class will escape the user input to prevent SQL injection
if ($_GET["Power"] != "*" && $_GET["Poles"] != "*") {
$stmt = $dbh->prepare("SELECT * FROM `TABLE 2` WHERE `Power` = :power AND `Poles` = :poles;");
$stmt->execute([
':power' => $_GET["Power"],
':poles' => $_GET["Poles"]
]);
} elseif ($_GET["Power"] != "*") {
$stmt = $dbh->prepare("SELECT * FROM `TABLE 2` WHERE `Power` = :power");
$stmt->execute([':power' => $_GET["Power"]]);
} elseif ($_GET["Poles"]) {
$stmt = $dbh->prepare("SELECT * FROM `TABLE 2` WHERE `Poles` = :poles;");
$stmt->execute([':power' => $_GET["Poles"]]);
} else {
$stmt = $dbh->prepare("SELECT * FROM `TABLE 2` ORDER BY `Power` ASC");
$stmt->execute();
}
if ($stmt->rowCount()) {
//The query returned results, which we can fetch in a variety of ways
//http://php.net/manual/en/pdostatement.fetch.php
//http://php.net/manual/en/pdostatement.fetchall.php
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
} else {
//No results, handle appropriately
}
如果if / elseif / else块看起来很粗糙,你实际上可以用switch语句完成同样的事情。将true作为要匹配的值传递,并使您的case语句成为定义每个案例的逻辑。匹配的第一个案例将运行,而如果没有案例匹配则默认运行。
这就是看起来的样子:
switch (true) {
case $_GET["Power"] != "*" && $_GET["Poles"] != "*":
$stmt = $dbh->prepare("SELECT * FROM `TABLE 2` WHERE `Power` = :power AND `Poles` = :poles;");
$stmt->execute([
':power' => $_GET["Power"],
':poles' => $_GET["Poles"]
]);
break;
case $_GET["Power"] != "*":
$stmt = $dbh->prepare("SELECT * FROM `TABLE 2` WHERE `Power` = :power");
$stmt->execute([':power' => $_GET["Power"]]);
break;
case $_GET["Poles"] != "*":
$stmt = $dbh->prepare("SELECT * FROM `TABLE 2` WHERE `Poles` = :poles;");
$stmt->execute([':power' => $_GET["Poles"]]);
break;
default:
$stmt = $dbh->prepare("SELECT * FROM `TABLE 2` ORDER BY `Power` ASC");
$stmt->execute();
break;
修改1:
对于它的价值,我倾向于避免尽可能多地暴露我的任何底层技术,因此使用用户可以看到和可能操作的默认SQL关键字/运算符是有问题的(对我而言)。因此,我不使用*或%作为用户可以传递给我的值。取而代之的是我可以在我的逻辑中使用其他占位符,例如空字符串,0或-1,具体取决于字段接受的内容。
使用PDO和绑定参数可以抵消用户输入恶意内容的风险,因此仅仅这样做会消除使用*或%的大量风险。在这种情况下,它只取决于您是否希望用户能够猜测您的底层存储引擎。
从性能的角度来看,我相信在WHERE子句中,相等运算符(=)将比LIKE运算符更快,但您可能只会注意到大型生产环境中的性能损失,因此不必担心。< / p>
答案 1 :(得分:1)
$query = "SELECT * FROM `TABLE 2` WHERE Power LIKE ".$_GET["Power"]." AND Poles LIKE ".$_GET["Poles"]."";
使用此查询将能够获得您想要的结果。请注意,我已将=
运算符更改为LIKE
。
然后,在您的用户表单或将值传递到$_GET
的方式中,您需要将*
更改为%
。 %
是MySQL的wilcard符号。
<强>另外强>
您在数据库查询中使用来自用户的输入,因此您应该始终使用预准备语句来避免SQL注入。
请参阅This SO Q&A哪两个非常容易遵循如何执行适当准备陈述的样本